Skip to content

Commit 909e178

Browse files
committed
typeck: fix ? operator suggestion span
1 parent ce06997 commit 909e178

File tree

1 file changed

+19
-12
lines changed

1 file changed

+19
-12
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,12 +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 mut span = expr.span;
1295-
while expr.span.eq_ctxt(span)
1296-
&& let Some(parent_callsite) = span.parent_callsite()
1297-
{
1298-
span = parent_callsite;
1299-
}
1294+
let span = find_local_most_ancestor_suggestable_span(expr.span);
13001295

13011296
let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
13021297
vec![(span.shrink_to_hi(), ".into()".to_owned())]
@@ -1901,12 +1896,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19011896
None => sugg.to_string(),
19021897
};
19031898

1904-
err.span_suggestion_verbose(
1905-
expr.span.shrink_to_hi(),
1906-
msg,
1907-
sugg,
1908-
Applicability::HasPlaceholders,
1909-
);
1899+
let span = find_local_most_ancestor_suggestable_span(expr.span);
1900+
err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders);
19101901
return true;
19111902
}
19121903

@@ -3180,3 +3171,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31803171
}
31813172
}
31823173
}
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+
}

0 commit comments

Comments
 (0)