pub struct NodeIndex(/* private fields */);Expand description
A unique index for a node within an AST.
Our encoding of 32-bit AST node indices is as follows:
u32::MAX(1111…1) is reserved as a forbidden value (mapped to 0 forNonZero)u32::MAX - 1(1111…0) is reserved forNodeIndex::NONE- The top two bits encode the sub-AST level:
- 00 is top-level AST
- 01 is sub-AST (string annotation)
- 10 is sub-sub-AST (string annotation in string annotation)
- 11 is forbidden (well, it only appears in the above reserved values)
- The remaining 30 bits are the real (sub)-AST node index
To get the first sub-index of a node’s sub-AST we:
- increment the sub-AST level in the high-bits
- at level 1, multiply the real index by 256
- at level 2, multiply the real index by 8
The multiplication gives each node a reserved space of 256 nodes for its sub-AST to work with (“should be enough for anybody”), and 8 nodes for a sub-sub-AST (enough for an identifier and maybe some simple unions).
Here are some implications:
- We have 2^30 top-level AST nodes (1 billion)
- To have a string annotation, the parent node needs to be multiplied by 256 without overflowing 30 bits, so string annotations cannot be used after 2^22 nodes (4 million), which would be like, a million lines of code.
- To have a sub-string annotation, the top-level node needs to be multiplied by 256 * 8, so sub-string annotations cannot be used after 2^19 nodes (500 thousand), or about 100k lines of code.
This feels like a pretty reasonable compromise that will work well in practice, although it creates some very wonky boundary conditions that will be very unpleasant if someone runs into them.
That said, string annotations are in many regards “legacy” and so new code ideally doesn’t have to use them, and there’s never a real reason to use sub-annotation let-alone a sub-sub-annotation.
Implementations§
Trait Implementations§
Source§impl GetSize for NodeIndex
impl GetSize for NodeIndex
Source§fn get_heap_size(&self) -> usize
fn get_heap_size(&self) -> usize
Source§fn get_heap_size_with_tracker<TRACKER>(
&self,
tracker: TRACKER,
) -> (usize, TRACKER)where
TRACKER: GetSizeTracker,
fn get_heap_size_with_tracker<TRACKER>(
&self,
tracker: TRACKER,
) -> (usize, TRACKER)where
TRACKER: GetSizeTracker,
tracker. Read moreSource§fn get_stack_size() -> usize
fn get_stack_size() -> usize
Source§fn get_size_with_tracker<T>(&self, tracker: T) -> (usize, T)where
T: GetSizeTracker,
fn get_size_with_tracker<T>(&self, tracker: T) -> (usize, T)where
T: GetSizeTracker,
tracker. Read moreSource§impl Ord for NodeIndex
impl Ord for NodeIndex
Source§impl PartialOrd for NodeIndex
impl PartialOrd for NodeIndex
impl Copy for NodeIndex
impl Eq for NodeIndex
impl StructuralPartialEq for NodeIndex
Auto Trait Implementations§
impl Freeze for NodeIndex
impl RefUnwindSafe for NodeIndex
impl Send for NodeIndex
impl Sync for NodeIndex
impl Unpin for NodeIndex
impl UnsafeUnpin for NodeIndex
impl UnwindSafe for NodeIndex
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more