@@ -401,6 +401,63 @@ impl Span {
401
401
} ) ,
402
402
}
403
403
}
404
+
405
+ // For optimization we are interested in cases in which the parent is inline and the parent
406
+ // update doesn't change format. All non-inline or format changing scenarios require accessing
407
+ // interner and can fall back to `Span::new`.
408
+ #[ inline]
409
+ pub fn with_parent ( self , parent : Option < LocalDefId > ) -> Span {
410
+ let data = match_span_kind ! {
411
+ self ,
412
+ InlineCtxt ( span) => {
413
+ // Only if the new parent is `None` the format will be preserved.
414
+ if parent. is_none( ) {
415
+ return self ;
416
+ }
417
+ span. data( )
418
+ } ,
419
+ InlineParent ( span) => {
420
+ // Any `Some` small new parent will preserve the format.
421
+ // `None` may change the format to `InlineCtxt` if ctxt and len are small enough.
422
+ if let Some ( parent) = parent
423
+ && let parent32 = parent. local_def_index. as_u32( )
424
+ && parent32 <= MAX_CTXT {
425
+ let old_parent = LocalDefId { local_def_index: DefIndex :: from_u32( span. parent as u32 ) } ;
426
+ // FIXME: Is this tracking necessary?
427
+ ( * SPAN_TRACK ) ( old_parent) ;
428
+ return InlineParent :: span( span. lo, span. len_with_tag, parent32 as u16 ) ;
429
+ }
430
+ span. data( )
431
+ } ,
432
+ PartiallyInterned ( span) => span. data( ) ,
433
+ Interned ( span) => span. data( ) ,
434
+ } ;
435
+
436
+ // We could not keep the span in the same inline format, fall back to the complete logic.
437
+ if let Some ( old_parent) = data. parent {
438
+ // FIXME: Is this tracking necessary?
439
+ ( * SPAN_TRACK ) ( old_parent) ;
440
+ }
441
+ data. with_parent ( parent)
442
+ }
443
+
444
+ #[ inline]
445
+ pub fn parent ( self ) -> Option < LocalDefId > {
446
+ let interned_parent =
447
+ |index : u32 | with_span_interner ( |interner| interner. spans [ index as usize ] . parent ) ;
448
+ let parent = match_span_kind ! {
449
+ self ,
450
+ InlineCtxt ( _span) => return None ,
451
+ InlineParent ( span) => Some ( LocalDefId { local_def_index: DefIndex :: from_u32( span. parent as u32 ) } ) ,
452
+ PartiallyInterned ( span) => interned_parent( span. index) ,
453
+ Interned ( span) => interned_parent( span. index) ,
454
+ } ;
455
+ if let Some ( parent) = parent {
456
+ // FIXME: Is this tracking necessary?
457
+ ( * SPAN_TRACK ) ( parent) ;
458
+ }
459
+ parent
460
+ }
404
461
}
405
462
406
463
#[ derive( Default ) ]
0 commit comments