@@ -28,12 +28,12 @@ use rustc_data_structures::fx::FxIndexSet;
28
28
/// Inline (compressed) format:
29
29
/// - `span.base_or_index == span_data.lo`
30
30
/// - `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 == span_data.ctxt` (must be `< MAX_CTXT`)
32
32
///
33
33
/// Interned format:
34
34
/// - `span.base_or_index == index` (indexes into the interner table)
35
35
/// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero)
36
- /// - `span.ctxt == 0`
36
+ /// - `span.ctxt == span_data.ctxt` (must be < `MAX_CTXT`) or `MAX_CTXT` otherwise
37
37
///
38
38
/// The inline form uses 0 for the tag value (rather than 1) so that we don't
39
39
/// need to mask out the tag bit when getting the length, and so that the
@@ -65,15 +65,15 @@ use rustc_data_structures::fx::FxIndexSet;
65
65
pub struct Span {
66
66
base_or_index : u32 ,
67
67
len_or_tag : u16 ,
68
- ctxt_or_zero : u16 ,
68
+ ctxt_or_max : u16 ,
69
69
}
70
70
71
71
const LEN_TAG : u16 = 0b1000_0000_0000_0000 ;
72
72
const MAX_LEN : u32 = 0b0111_1111_1111_1111 ;
73
73
const MAX_CTXT : u32 = 0b1111_1111_1111_1111 ;
74
74
75
75
/// 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_zero : 0 } ;
76
+ pub const DUMMY_SP : Span = Span { base_or_index : 0 , len_or_tag : 0 , ctxt_or_max : 0 } ;
77
77
78
78
impl Span {
79
79
#[ inline]
@@ -89,14 +89,15 @@ impl Span {
89
89
90
90
let ( base, len, ctxt2) = ( lo. 0 , hi. 0 - lo. 0 , ctxt. as_u32 ( ) ) ;
91
91
92
- if len <= MAX_LEN && ctxt2 <= MAX_CTXT && parent. is_none ( ) {
92
+ if len <= MAX_LEN && ctxt2 < MAX_CTXT && parent. is_none ( ) {
93
93
// Inline format.
94
- Span { base_or_index : base, len_or_tag : len as u16 , ctxt_or_zero : ctxt2 as u16 }
94
+ Span { base_or_index : base, len_or_tag : len as u16 , ctxt_or_max : ctxt2 as u16 }
95
95
} else {
96
96
// Interned format.
97
97
let index =
98
98
with_span_interner ( |interner| interner. intern ( & SpanData { lo, hi, ctxt, parent } ) ) ;
99
- Span { base_or_index : index, len_or_tag : LEN_TAG , ctxt_or_zero : 0 }
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 }
100
101
}
101
102
}
102
103
@@ -119,16 +120,29 @@ impl Span {
119
120
SpanData {
120
121
lo : BytePos ( self . base_or_index ) ,
121
122
hi : BytePos ( self . base_or_index + self . len_or_tag as u32 ) ,
122
- ctxt : SyntaxContext :: from_u32 ( self . ctxt_or_zero as u32 ) ,
123
+ ctxt : SyntaxContext :: from_u32 ( self . ctxt_or_max as u32 ) ,
123
124
parent : None ,
124
125
}
125
126
} else {
126
127
// Interned format.
127
- debug_assert ! ( self . ctxt_or_zero == 0 ) ;
128
128
let index = self . base_or_index ;
129
129
with_span_interner ( |interner| interner. spans [ index as usize ] )
130
130
}
131
131
}
132
+
133
+ /// This function is used as a fast path when decoding the full `SpanData` is not necessary.
134
+ #[ inline]
135
+ pub fn ctxt ( self ) -> SyntaxContext {
136
+ let ctxt_or_max = self . ctxt_or_max as u32 ;
137
+ if ctxt_or_max < MAX_CTXT {
138
+ // Inline format or interned format with inline ctxt.
139
+ SyntaxContext :: from_u32 ( ctxt_or_max)
140
+ } else {
141
+ // Interned format.
142
+ let index = self . base_or_index ;
143
+ with_span_interner ( |interner| interner. spans [ index as usize ] . ctxt )
144
+ }
145
+ }
132
146
}
133
147
134
148
#[ derive( Default ) ]
0 commit comments