1
Fork 0

typeck: fix ? operator suggestion span

This commit is contained in:
许杰友 Jieyou Xu (Joe) 2024-04-08 21:42:06 +00:00
parent a809ec96f3
commit 4606485d0c
2 changed files with 42 additions and 12 deletions

View file

@ -1291,12 +1291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::TraitRef::new(self.tcx, into_def_id, [expr_ty, expected_ty]), ty::TraitRef::new(self.tcx, into_def_id, [expr_ty, expected_ty]),
)) ))
{ {
let mut span = expr.span; let span = expr.span.find_oldest_ancestor_in_same_ctxt();
while expr.span.eq_ctxt(span)
&& let Some(parent_callsite) = span.parent_callsite()
{
span = parent_callsite;
}
let mut sugg = if expr.precedence().order() >= PREC_POSTFIX { let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
vec![(span.shrink_to_hi(), ".into()".to_owned())] vec![(span.shrink_to_hi(), ".into()".to_owned())]
@ -1901,12 +1896,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None => sugg.to_string(), None => sugg.to_string(),
}; };
err.span_suggestion_verbose( let span = expr.span.find_oldest_ancestor_in_same_ctxt();
expr.span.shrink_to_hi(), err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders);
msg,
sugg,
Applicability::HasPlaceholders,
);
return true; return true;
} }

View file

@ -743,6 +743,45 @@ impl Span {
Some(self) Some(self)
} }
/// Recursively walk down the expansion ancestors to find the oldest ancestor span with the same
/// [`SyntaxContext`] the initial span.
///
/// This method is suitable for peeling through *local* macro expansions to find the "innermost"
/// span that is still local and shares the same [`SyntaxContext`]. For example, given
///
/// ```ignore (illustrative example, contains type error)
/// macro_rules! outer {
/// ($x: expr) => {
/// inner!($x)
/// }
/// }
///
/// macro_rules! inner {
/// ($x: expr) => {
/// format!("error: {}", $x)
/// //~^ ERROR mismatched types
/// }
/// }
///
/// fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
/// Err(outer!(x))
/// }
/// ```
///
/// if provided the initial span of `outer!(x)` inside `bar`, this method will recurse
/// the parent callsites until we reach `format!("error: {}", $x)`, at which point it is the
/// oldest ancestor span that is both still local and shares the same [`SyntaxContext`] as the
/// initial span.
pub fn find_oldest_ancestor_in_same_ctxt(self) -> Span {
let mut cur = self;
while cur.eq_ctxt(self)
&& let Some(parent_callsite) = cur.parent_callsite()
{
cur = parent_callsite;
}
cur
}
/// Edition of the crate from which this span came. /// Edition of the crate from which this span came.
pub fn edition(self) -> edition::Edition { pub fn edition(self) -> edition::Edition {
self.ctxt().edition() self.ctxt().edition()