@@ -136,13 +136,13 @@ impl Span {
136
136
}
137
137
138
138
// Partially-interned or fully-interned format.
139
- let index =
140
- with_span_interner ( |interner| interner. intern ( & SpanData { lo, hi, ctxt, parent } ) ) ;
141
- let ctxt_or_parent_or_marker = if ctxt2 <= MAX_CTXT {
142
- ctxt2 as u16 // partially-interned
139
+ let ( ctxt_or_parent_or_marker, ctxt) = if ctxt2 <= MAX_CTXT {
140
+ ( ctxt2 as u16 , SyntaxContext :: from_u32 ( u32:: MAX ) ) // partially-interned
143
141
} else {
144
- CTXT_INTERNED_MARKER // fully-interned
142
+ ( CTXT_INTERNED_MARKER , ctxt ) // fully-interned
145
143
} ;
144
+ let index =
145
+ with_span_interner ( |interner| interner. intern ( & SpanData { lo, hi, ctxt, parent } ) ) ;
146
146
Span {
147
147
lo_or_index : index,
148
148
len_with_tag_or_marker : BASE_LEN_INTERNED_MARKER ,
@@ -193,7 +193,11 @@ impl Span {
193
193
// the interned value contains all the data, so we don't need to
194
194
// distinguish them.
195
195
let index = self . lo_or_index ;
196
- with_span_interner ( |interner| interner. spans [ index as usize ] )
196
+ let mut data = with_span_interner ( |interner| interner. spans [ index as usize ] ) ;
197
+ if data. ctxt . as_u32 ( ) == u32:: MAX {
198
+ data. ctxt = SyntaxContext :: from_u32 ( u32:: from ( self . ctxt_or_parent_or_marker ) ) ;
199
+ }
200
+ data
197
201
}
198
202
}
199
203
@@ -236,6 +240,46 @@ impl Span {
236
240
} )
237
241
}
238
242
243
+ pub fn update_ctxt ( & mut self , update : impl FnOnce ( SyntaxContext ) -> SyntaxContext ) {
244
+ let updated_ctxt32;
245
+ let data;
246
+ if self . len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
247
+ if self . len_with_tag_or_marker & PARENT_TAG == 0 {
248
+ // Inline-context format.
249
+ updated_ctxt32 =
250
+ update ( SyntaxContext :: from_u32 ( self . ctxt_or_parent_or_marker as u32 ) ) . as_u32 ( ) ;
251
+ if updated_ctxt32 <= MAX_CTXT {
252
+ self . ctxt_or_parent_or_marker = updated_ctxt32 as u16 ;
253
+ return ;
254
+ }
255
+ } else {
256
+ // Inline-parent format. We know that the SyntaxContext is root.
257
+ updated_ctxt32 = update ( SyntaxContext :: root ( ) ) . as_u32 ( ) ;
258
+ if updated_ctxt32 == 0 {
259
+ // do nothing
260
+ return ;
261
+ }
262
+ }
263
+ data = self . data_untracked ( ) ;
264
+ } else if self . ctxt_or_parent_or_marker != CTXT_INTERNED_MARKER {
265
+ // Partially-interned format. This path avoids looking up the
266
+ // interned value, and is the whole point of the
267
+ // partially-interned format.
268
+ updated_ctxt32 =
269
+ update ( SyntaxContext :: from_u32 ( self . ctxt_or_parent_or_marker as u32 ) ) . as_u32 ( ) ;
270
+ if updated_ctxt32 <= MAX_CTXT {
271
+ self . ctxt_or_parent_or_marker = updated_ctxt32 as u16 ;
272
+ return ;
273
+ }
274
+ data = self . data_untracked ( ) ;
275
+ } else {
276
+ data = self . data_untracked ( ) ;
277
+ updated_ctxt32 = update ( data. ctxt ) . as_u32 ( ) ;
278
+ } ;
279
+
280
+ * self = data. with_ctxt ( SyntaxContext :: from_u32 ( updated_ctxt32) ) ;
281
+ }
282
+
239
283
/// This function is used as a fast path when decoding the full `SpanData` is not necessary.
240
284
/// It's a cut-down version of `data_untracked`.
241
285
#[ cfg_attr( not( test) , rustc_diagnostic_item = "SpanCtxt" ) ]
0 commit comments