@@ -322,29 +322,28 @@ impl Span {
322
322
}
323
323
}
324
324
325
- // For optimization we are interested in cases in which the context is inline and the context
326
- // update doesn't change format. All non-inline or format changing scenarios require accessing
327
- // interner and can fall back to `Span::new`.
328
325
#[ inline]
329
- pub fn map_ctxt ( self , update : impl FnOnce ( SyntaxContext ) -> SyntaxContext ) -> Span {
330
- match_span_kind ! {
326
+ pub fn map_ctxt ( self , map : impl FnOnce ( SyntaxContext ) -> SyntaxContext ) -> Span {
327
+ let data = match_span_kind ! {
331
328
self ,
332
329
InlineCtxt ( span) => {
333
- let updated_ctxt32 = update( SyntaxContext :: from_u16( span. ctxt) ) . as_u32( ) ;
334
- // Any small new context including zero will preserve the format.
335
- return if updated_ctxt32 <= MAX_CTXT {
336
- InlineCtxt :: span( span. lo, span. len, updated_ctxt32 as u16 )
330
+ // This format occurs 1-2 orders of magnitude more often than others (#125017),
331
+ // so it makes sense to micro-optimize it to avoid `span.data()` and `Span::new()`.
332
+ let new_ctxt = map( SyntaxContext :: from_u16( span. ctxt) ) ;
333
+ let new_ctxt32 = new_ctxt. as_u32( ) ;
334
+ return if new_ctxt32 <= MAX_CTXT {
335
+ // Any small new context including zero will preserve the format.
336
+ InlineCtxt :: span( span. lo, span. len, new_ctxt32 as u16 )
337
337
} else {
338
- span. data( ) . with_ctxt( SyntaxContext :: from_u32 ( updated_ctxt32 ) )
338
+ span. data( ) . with_ctxt( new_ctxt )
339
339
} ;
340
340
} ,
341
- InlineParent ( _span ) => { } ,
342
- PartiallyInterned ( _span ) => { } ,
343
- Interned ( _span ) => { } ,
344
- }
341
+ InlineParent ( span ) => span . data ( ) ,
342
+ PartiallyInterned ( span ) => span . data ( ) ,
343
+ Interned ( span ) => span . data ( ) ,
344
+ } ;
345
345
346
- let data = self . data_untracked ( ) ;
347
- data. with_ctxt ( update ( data. ctxt ) )
346
+ data. with_ctxt ( map ( data. ctxt ) )
348
347
}
349
348
350
349
// Returns either syntactic context, if it can be retrieved without taking the interner lock,
@@ -381,6 +380,56 @@ impl Span {
381
380
} ) ,
382
381
}
383
382
}
383
+
384
+ #[ inline]
385
+ pub fn with_parent ( self , parent : Option < LocalDefId > ) -> Span {
386
+ let data = match_span_kind ! {
387
+ self ,
388
+ InlineCtxt ( span) => {
389
+ // This format occurs 1-2 orders of magnitude more often than others (#126544),
390
+ // so it makes sense to micro-optimize it to avoid `span.data()` and `Span::new()`.
391
+ if parent. is_none( ) {
392
+ // Only if the new parent is `None` the format will be preserved.
393
+ return self ;
394
+ } else if span. ctxt == 0
395
+ && let Some ( parent) = parent
396
+ && let parent32 = parent. local_def_index. as_u32( )
397
+ && parent32 <= MAX_CTXT
398
+ {
399
+ // Otherwise the new format may be `InlineParent` if the new parent is small.
400
+ return InlineParent :: span( span. lo, span. len, parent32 as u16 ) ;
401
+ }
402
+ span. data( )
403
+ } ,
404
+ InlineParent ( span) => span. data( ) ,
405
+ PartiallyInterned ( span) => span. data( ) ,
406
+ Interned ( span) => span. data( ) ,
407
+ } ;
408
+
409
+ if let Some ( old_parent) = data. parent {
410
+ // FIXME: Is this tracking necessary?
411
+ ( * SPAN_TRACK ) ( old_parent) ;
412
+ }
413
+ data. with_parent ( parent)
414
+ }
415
+
416
+ #[ inline]
417
+ pub fn parent ( self ) -> Option < LocalDefId > {
418
+ let interned_parent =
419
+ |index : u32 | with_span_interner ( |interner| interner. spans [ index as usize ] . parent ) ;
420
+ let parent = match_span_kind ! {
421
+ self ,
422
+ InlineCtxt ( _span) => return None ,
423
+ InlineParent ( span) => Some ( LocalDefId { local_def_index: DefIndex :: from_u16( span. parent) } ) ,
424
+ PartiallyInterned ( span) => interned_parent( span. index) ,
425
+ Interned ( span) => interned_parent( span. index) ,
426
+ } ;
427
+ if let Some ( parent) = parent {
428
+ // FIXME: Is this tracking necessary?
429
+ ( * SPAN_TRACK ) ( parent) ;
430
+ }
431
+ parent
432
+ }
384
433
}
385
434
386
435
#[ derive( Default ) ]
0 commit comments