Skip to content

Commit e628dfb

Browse files
committed
refactor: move helper to be method on Span
1 parent d7f7be2 commit e628dfb

File tree

2 files changed

+41
-18
lines changed

2 files changed

+41
-18
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+2-18
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12911291
ty::TraitRef::new(self.tcx, into_def_id, [expr_ty, expected_ty]),
12921292
))
12931293
{
1294-
let span = find_local_most_ancestor_suggestable_span(expr.span);
1294+
let span = expr.span.find_local_most_ancestor_suggestable_span();
12951295

12961296
let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
12971297
vec![(span.shrink_to_hi(), ".into()".to_owned())]
@@ -1896,7 +1896,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18961896
None => sugg.to_string(),
18971897
};
18981898

1899-
let span = find_local_most_ancestor_suggestable_span(expr.span);
1899+
let span = expr.span.find_local_most_ancestor_suggestable_span();
19001900
err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders);
19011901
return true;
19021902
}
@@ -3171,19 +3171,3 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31713171
}
31723172
}
31733173
}
3174-
3175-
/// For suggestion span, recursively try to look for the ancestor span which shares the same syntax
3176-
/// context as the initially provided `span`. This will recursively look into local macros until the
3177-
/// span inside the most ancestor local macro is found. It will stop recursing as soon as the
3178-
/// syntax context of a potential parent callsite changes, such as if the potential parent callsite
3179-
/// is in a foreign macro. This helps to prevent leaking implementation details from upstream
3180-
/// crates and stdlib crates that the user likely have no control over.
3181-
fn find_local_most_ancestor_suggestable_span(initial_span: Span) -> Span {
3182-
let mut span = initial_span;
3183-
while initial_span.eq_ctxt(span)
3184-
&& let Some(parent_callsite) = span.parent_callsite()
3185-
{
3186-
span = parent_callsite;
3187-
}
3188-
span
3189-
}

compiler/rustc_span/src/lib.rs

+39
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,45 @@ impl Span {
743743
Some(self)
744744
}
745745

746+
/// Recursively walk down the expansion ancestors to find the most ancestor span with the same
747+
/// [`SyntaxContext`] as `initial`.
748+
///
749+
/// This method is suitable for peeling through *local* macro expansions to find the "innermost"
750+
/// span that is still local and shares the same [`SyntaxContext`]. For example, given
751+
///
752+
/// ```ignore (illustrative example, contains type error)
753+
/// macro_rules! outer {
754+
/// ($x: expr) => {
755+
/// inner!($x)
756+
/// }
757+
/// }
758+
///
759+
/// macro_rules! inner {
760+
/// ($x: expr) => {
761+
/// format!("error: {}", $x)
762+
/// //~^ ERROR mismatched types
763+
/// }
764+
/// }
765+
///
766+
/// fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
767+
/// Err(outer!(x))
768+
/// }
769+
/// ```
770+
///
771+
/// if provided the `initial` span of `outer!(x)` inside `bar`, this method will recurse
772+
/// the parent callsites until we reach `format!("error: {}", $x)`, at which point it is the
773+
/// most ancestor span that is both still local and shares the same [`SyntaxContext`] as the
774+
/// `initial` span.
775+
pub fn find_local_most_ancestor_suggestable_span(self) -> Span {
776+
let mut cur = self;
777+
while cur.eq_ctxt(self)
778+
&& let Some(parent_callsite) = cur.parent_callsite()
779+
{
780+
cur = parent_callsite;
781+
}
782+
cur
783+
}
784+
746785
/// Edition of the crate from which this span came.
747786
pub fn edition(self) -> edition::Edition {
748787
self.ctxt().edition()

0 commit comments

Comments
 (0)