mirror of
https://github.com/RGBCube/cstree
synced 2025-07-27 09:07:44 +00:00
Use strict provenance for pointer tagging (#36)
This commit is contained in:
parent
f187aba06c
commit
2ffeb0e166
7 changed files with 18 additions and 6 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
@ -102,7 +102,7 @@ jobs:
|
||||||
rust-version: nightly
|
rust-version: nightly
|
||||||
components: miri
|
components: miri
|
||||||
env:
|
env:
|
||||||
MIRIFLAGS: -Zmiri-disable-isolation
|
MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance
|
||||||
- run: cargo miri test --verbose --all-features
|
- run: cargo miri test --verbose --all-features
|
||||||
|
|
||||||
sanitizers:
|
sanitizers:
|
||||||
|
|
|
@ -22,6 +22,7 @@ parking_lot = "0.11.2"
|
||||||
|
|
||||||
# Arc
|
# Arc
|
||||||
triomphe = "0.1.3"
|
triomphe = "0.1.3"
|
||||||
|
sptr = "0.3.2"
|
||||||
|
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
|
|
@ -4,6 +4,8 @@ use std::{fmt, hash, mem};
|
||||||
// This MUST be size=1 such that pointer math actually advances the pointer.
|
// This MUST be size=1 such that pointer math actually advances the pointer.
|
||||||
type ErasedPtr = *const u8;
|
type ErasedPtr = *const u8;
|
||||||
|
|
||||||
|
use sptr::Strict;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
green::{GreenNode, GreenToken, SyntaxKind},
|
green::{GreenNode, GreenToken, SyntaxKind},
|
||||||
NodeOrToken, TextSize,
|
NodeOrToken, TextSize,
|
||||||
|
@ -114,7 +116,7 @@ impl From<PackedGreenElement> for GreenElement {
|
||||||
|
|
||||||
impl PackedGreenElement {
|
impl PackedGreenElement {
|
||||||
pub(crate) fn is_node(&self) -> bool {
|
pub(crate) fn is_node(&self) -> bool {
|
||||||
self.ptr as usize & 1 == 0
|
self.ptr.addr() & super::token::IS_TOKEN_TAG == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn as_node(&self) -> Option<&GreenNode> {
|
pub(crate) fn as_node(&self) -> Option<&GreenNode> {
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
interning::{Key, Resolver},
|
interning::{Key, Resolver},
|
||||||
TextSize,
|
TextSize,
|
||||||
};
|
};
|
||||||
|
use sptr::Strict;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
#[repr(align(2))] // to use 1 bit for pointer tagging. NB: this is an at-least annotation
|
#[repr(align(2))] // to use 1 bit for pointer tagging. NB: this is an at-least annotation
|
||||||
|
@ -23,17 +24,18 @@ pub struct GreenToken {
|
||||||
unsafe impl Send for GreenToken {} // where GreenTokenData: Send + Sync
|
unsafe impl Send for GreenToken {} // where GreenTokenData: Send + Sync
|
||||||
unsafe impl Sync for GreenToken {} // where GreenTokenData: Send + Sync
|
unsafe impl Sync for GreenToken {} // where GreenTokenData: Send + Sync
|
||||||
|
|
||||||
|
pub(super) const IS_TOKEN_TAG: usize = 0x1;
|
||||||
impl GreenToken {
|
impl GreenToken {
|
||||||
fn add_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> {
|
fn add_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = ((ptr.as_ptr() as usize) | 1) as *mut GreenTokenData;
|
let ptr = ptr.as_ptr().map_addr(|addr| addr | IS_TOKEN_TAG);
|
||||||
ptr::NonNull::new_unchecked(ptr)
|
ptr::NonNull::new_unchecked(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> {
|
fn remove_tag(ptr: ptr::NonNull<GreenTokenData>) -> ptr::NonNull<GreenTokenData> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = ((ptr.as_ptr() as usize) & !1) as *mut GreenTokenData;
|
let ptr = ptr.as_ptr().map_addr(|addr| addr & !IS_TOKEN_TAG);
|
||||||
ptr::NonNull::new_unchecked(ptr)
|
ptr::NonNull::new_unchecked(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
|
|
||||||
#![forbid(missing_debug_implementations, unconditional_recursion)]
|
#![forbid(missing_debug_implementations, unconditional_recursion)]
|
||||||
#![deny(unsafe_code, missing_docs, future_incompatible)]
|
#![deny(unsafe_code, missing_docs, future_incompatible)]
|
||||||
|
#![allow(unstable_name_collisions)] // strict provenance - must come after `future_incompatible` to take precedence
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
mod green;
|
mod green;
|
||||||
|
|
|
@ -387,7 +387,8 @@ impl<L: Language, D> SyntaxNode<L, D> {
|
||||||
/// builder.token(TOKEN, "content");
|
/// builder.token(TOKEN, "content");
|
||||||
/// builder.finish_node();
|
/// builder.finish_node();
|
||||||
/// let (green, cache) = builder.finish();
|
/// let (green, cache) = builder.finish();
|
||||||
/// let root: ResolvedNode<Lang> = SyntaxNode::new_root_with_resolver(green, cache.unwrap().into_interner().unwrap());
|
/// let root: ResolvedNode<Lang> =
|
||||||
|
/// SyntaxNode::new_root_with_resolver(green, cache.unwrap().into_interner().unwrap());
|
||||||
/// assert_eq!(root.text(), "content");
|
/// assert_eq!(root.text(), "content");
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -253,7 +253,12 @@ impl<L: Language, D> SyntaxToken<L, D> {
|
||||||
/// let tree = parse(&mut builder, "x");
|
/// let tree = parse(&mut builder, "x");
|
||||||
/// # let tree = SyntaxNode::<Lang>::new_root(builder.finish().0);
|
/// # let tree = SyntaxNode::<Lang>::new_root(builder.finish().0);
|
||||||
/// let type_table = &state.type_table;
|
/// let type_table = &state.type_table;
|
||||||
/// let ident = tree.children_with_tokens().next().unwrap().into_token().unwrap();
|
/// let ident = tree
|
||||||
|
/// .children_with_tokens()
|
||||||
|
/// .next()
|
||||||
|
/// .unwrap()
|
||||||
|
/// .into_token()
|
||||||
|
/// .unwrap();
|
||||||
/// let typ = type_table.type_of(ident.text_key());
|
/// let typ = type_table.type_of(ident.text_key());
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue