Skip to content

Commit eab5a5b

Browse files
committed
Auto merge of #126544 - petrochenkov:upparent, r=<try>
rustc_span: Optimize span parent get/set methods Like #125017, but for span parents. r? `@cjgillot`
2 parents 12b33d3 + 90b72b5 commit eab5a5b

File tree

2 files changed

+59
-9
lines changed

2 files changed

+59
-9
lines changed

compiler/rustc_span/src/lib.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,9 @@ impl SpanData {
525525
fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
526526
Span::new(self.lo, self.hi, ctxt, self.parent)
527527
}
528+
/// Avoid if possible, `Span::with_parent` should be preferred.
528529
#[inline]
529-
pub fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
530+
fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
530531
Span::new(self.lo, self.hi, self.ctxt, parent)
531532
}
532533
/// Returns `true` if this is a dummy span with any hygienic context.
@@ -580,14 +581,6 @@ impl Span {
580581
pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
581582
self.map_ctxt(|_| ctxt)
582583
}
583-
#[inline]
584-
pub fn parent(self) -> Option<LocalDefId> {
585-
self.data().parent
586-
}
587-
#[inline]
588-
pub fn with_parent(self, ctxt: Option<LocalDefId>) -> Span {
589-
self.data().with_parent(ctxt)
590-
}
591584

592585
#[inline]
593586
pub fn is_visible(self, sm: &SourceMap) -> bool {

compiler/rustc_span/src/span_encoding.rs

+57
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,63 @@ impl Span {
401401
}),
402402
}
403403
}
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+
}
404461
}
405462

406463
#[derive(Default)]

0 commit comments

Comments
 (0)