@@ -28,12 +28,17 @@ use rustc_data_structures::fx::FxIndexSet;
2828/// Inline (compressed) format:
2929/// - `span.base_or_index == span_data.lo`
3030/// - `span.len_or_tag == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`)
31- /// - `span.ctxt == span_data.ctxt` (must be `< MAX_CTXT`)
31+ /// - `span.ctxt_or_tag == span_data.ctxt` (must be `<= MAX_CTXT`)
32+ ///
33+ /// Interned format with inline `SyntaxContext`:
34+ /// - `span.base_or_index == index` (indexes into the interner table)
35+ /// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero)
36+ /// - `span.ctxt_or_tag == span_data.ctxt` (must be `<= MAX_CTXT`)
3237///
3338/// Interned format:
3439/// - `span.base_or_index == index` (indexes into the interner table)
3540/// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero)
36- /// - `span.ctxt == span_data.ctxt` (must be < `MAX_CTXT`) or `MAX_CTXT` otherwise
41+ /// - `span.ctxt_or_tag == CTXT_TAG`
3742///
3843/// The inline form uses 0 for the tag value (rather than 1) so that we don't
3944/// need to mask out the tag bit when getting the length, and so that the
@@ -50,10 +55,10 @@ use rustc_data_structures::fx::FxIndexSet;
5055/// at 3 or 4, and then it drops off quickly from 8 onwards. 15 bits is enough
5156/// for 99.99%+ of cases, but larger values (sometimes 20+ bits) might occur
5257/// dozens of times in a typical crate.
53- /// - `ctxt ` is 16 bits in `Span` and 32 bits in `SpanData`, which means that
58+ /// - `ctxt_or_tag ` is 16 bits in `Span` and 32 bits in `SpanData`, which means that
5459/// large `ctxt` values will cause interning. The number of bits needed for
5560/// `ctxt` values depend partly on the crate size and partly on the form of
56- /// the code. No crates in `rustc-perf` need more than 15 bits for `ctxt `,
61+ /// the code. No crates in `rustc-perf` need more than 15 bits for `ctxt_or_tag `,
5762/// but larger crates might need more than 16 bits.
5863///
5964/// In order to reliably use parented spans in incremental compilation,
@@ -65,15 +70,16 @@ use rustc_data_structures::fx::FxIndexSet;
6570pub struct Span {
6671 base_or_index : u32 ,
6772 len_or_tag : u16 ,
68- ctxt_or_max : u16 ,
73+ ctxt_or_tag : u16 ,
6974}
7075
7176const LEN_TAG : u16 = 0b1000_0000_0000_0000 ;
7277const MAX_LEN : u32 = 0b0111_1111_1111_1111 ;
73- const MAX_CTXT : u32 = 0b1111_1111_1111_1111 ;
78+ const CTXT_TAG : u32 = 0b1111_1111_1111_1111 ;
79+ const MAX_CTXT : u32 = CTXT_TAG - 1 ;
7480
7581/// Dummy span, both position and length are zero, syntax context is zero as well.
76- pub const DUMMY_SP : Span = Span { base_or_index : 0 , len_or_tag : 0 , ctxt_or_max : 0 } ;
82+ pub const DUMMY_SP : Span = Span { base_or_index : 0 , len_or_tag : 0 , ctxt_or_tag : 0 } ;
7783
7884impl Span {
7985 #[ inline]
@@ -89,15 +95,15 @@ impl Span {
8995
9096 let ( base, len, ctxt2) = ( lo. 0 , hi. 0 - lo. 0 , ctxt. as_u32 ( ) ) ;
9197
92- if len <= MAX_LEN && ctxt2 < MAX_CTXT && parent. is_none ( ) {
98+ if len <= MAX_LEN && ctxt2 <= MAX_CTXT && parent. is_none ( ) {
9399 // Inline format.
94- Span { base_or_index : base, len_or_tag : len as u16 , ctxt_or_max : ctxt2 as u16 }
100+ Span { base_or_index : base, len_or_tag : len as u16 , ctxt_or_tag : ctxt2 as u16 }
95101 } else {
96102 // Interned format.
97103 let index =
98104 with_span_interner ( |interner| interner. intern ( & SpanData { lo, hi, ctxt, parent } ) ) ;
99- let ctxt_or_max = if ctxt2 < MAX_CTXT { ctxt2 } else { MAX_CTXT } as u16 ;
100- Span { base_or_index : index, len_or_tag : LEN_TAG , ctxt_or_max }
105+ let ctxt_or_tag = if ctxt2 <= MAX_CTXT { ctxt2 } else { CTXT_TAG } as u16 ;
106+ Span { base_or_index : index, len_or_tag : LEN_TAG , ctxt_or_tag }
101107 }
102108 }
103109
@@ -120,7 +126,7 @@ impl Span {
120126 SpanData {
121127 lo : BytePos ( self . base_or_index ) ,
122128 hi : BytePos ( self . base_or_index + self . len_or_tag as u32 ) ,
123- ctxt : SyntaxContext :: from_u32 ( self . ctxt_or_max as u32 ) ,
129+ ctxt : SyntaxContext :: from_u32 ( self . ctxt_or_tag as u32 ) ,
124130 parent : None ,
125131 }
126132 } else {
@@ -133,10 +139,10 @@ impl Span {
133139 /// This function is used as a fast path when decoding the full `SpanData` is not necessary.
134140 #[ inline]
135141 pub fn ctxt ( self ) -> SyntaxContext {
136- let ctxt_or_max = self . ctxt_or_max as u32 ;
137- if ctxt_or_max < MAX_CTXT {
142+ let ctxt_or_tag = self . ctxt_or_tag as u32 ;
143+ if ctxt_or_tag <= MAX_CTXT {
138144 // Inline format or interned format with inline ctxt.
139- SyntaxContext :: from_u32 ( ctxt_or_max )
145+ SyntaxContext :: from_u32 ( ctxt_or_tag )
140146 } else {
141147 // Interned format.
142148 let index = self . base_or_index ;
0 commit comments