Create two methods to fix find_oldest_ancestor_in_same_ctxt
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
This commit is contained in:
@@ -341,7 +341,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
|
} else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
|
||||||
let sp = info.span.find_oldest_ancestor_in_same_ctxt();
|
let sp = info.span.find_ancestor_not_from_macro().unwrap_or(info.span);
|
||||||
if info.tail_result_is_ignored {
|
if info.tail_result_is_ignored {
|
||||||
// #85581: If the first mutable borrow's scope contains
|
// #85581: If the first mutable borrow's scope contains
|
||||||
// the second borrow, this suggestion isn't helpful.
|
// the second borrow, this suggestion isn't helpful.
|
||||||
|
|||||||
@@ -1302,7 +1302,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
None => ".clone()".to_string(),
|
None => ".clone()".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt().shrink_to_hi();
|
let span = expr.span.find_ancestor_not_from_macro().unwrap_or(expr.span).shrink_to_hi();
|
||||||
|
|
||||||
diag.span_suggestion_verbose(
|
diag.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
@@ -1395,7 +1395,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.macro_backtrace()
|
.macro_backtrace()
|
||||||
.any(|x| matches!(x.kind, ExpnKind::Macro(MacroKind::Attr | MacroKind::Derive, ..)))
|
.any(|x| matches!(x.kind, ExpnKind::Macro(MacroKind::Attr | MacroKind::Derive, ..)))
|
||||||
{
|
{
|
||||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
let span = expr
|
||||||
|
.span
|
||||||
|
.find_ancestor_not_from_extern_macro(&self.tcx.sess.source_map())
|
||||||
|
.unwrap_or(expr.span);
|
||||||
|
|
||||||
let mut sugg = if self.precedence(expr) >= ExprPrecedence::Unambiguous {
|
let mut sugg = if self.precedence(expr) >= ExprPrecedence::Unambiguous {
|
||||||
vec![(span.shrink_to_hi(), ".into()".to_owned())]
|
vec![(span.shrink_to_hi(), ".into()".to_owned())]
|
||||||
@@ -2062,7 +2065,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
None => sugg.to_string(),
|
None => sugg.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
let span = expr
|
||||||
|
.span
|
||||||
|
.find_ancestor_not_from_extern_macro(&self.tcx.sess.source_map())
|
||||||
|
.unwrap_or(expr.span);
|
||||||
err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders);
|
err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||||||
let mut op_warned = false;
|
let mut op_warned = false;
|
||||||
|
|
||||||
if let Some(must_use_op) = must_use_op {
|
if let Some(must_use_op) = must_use_op {
|
||||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
let span = expr.span.find_ancestor_not_from_macro().unwrap_or(expr.span);
|
||||||
cx.emit_span_lint(
|
cx.emit_span_lint(
|
||||||
UNUSED_MUST_USE,
|
UNUSED_MUST_USE,
|
||||||
expr.span,
|
expr.span,
|
||||||
@@ -511,7 +511,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
MustUsePath::Def(span, def_id, reason) => {
|
MustUsePath::Def(span, def_id, reason) => {
|
||||||
let span = span.find_oldest_ancestor_in_same_ctxt();
|
let span = span.find_ancestor_not_from_macro().unwrap_or(*span);
|
||||||
cx.emit_span_lint(
|
cx.emit_span_lint(
|
||||||
UNUSED_MUST_USE,
|
UNUSED_MUST_USE,
|
||||||
span,
|
span,
|
||||||
|
|||||||
@@ -716,12 +716,17 @@ impl Span {
|
|||||||
(!ctxt.is_root()).then(|| ctxt.outer_expn_data().call_site)
|
(!ctxt.is_root()).then(|| ctxt.outer_expn_data().call_site)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walk down the expansion ancestors to find a span that's contained within `outer`.
|
/// Find the first ancestor span that's contained within `outer`.
|
||||||
///
|
///
|
||||||
/// The span returned by this method may have a different [`SyntaxContext`] as `outer`.
|
/// This method traverses the macro expansion ancestors until it finds the first span
|
||||||
|
/// that's contained within `outer`.
|
||||||
|
///
|
||||||
|
/// The span returned by this method may have a different [`SyntaxContext`] than `outer`.
|
||||||
/// If you need to extend the span, use [`find_ancestor_inside_same_ctxt`] instead,
|
/// If you need to extend the span, use [`find_ancestor_inside_same_ctxt`] instead,
|
||||||
/// because joining spans with different syntax contexts can create unexpected results.
|
/// because joining spans with different syntax contexts can create unexpected results.
|
||||||
///
|
///
|
||||||
|
/// This is used to find the span of the macro call when a parent expr span, i.e. `outer`, is known.
|
||||||
|
///
|
||||||
/// [`find_ancestor_inside_same_ctxt`]: Self::find_ancestor_inside_same_ctxt
|
/// [`find_ancestor_inside_same_ctxt`]: Self::find_ancestor_inside_same_ctxt
|
||||||
pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
|
pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
|
||||||
while !outer.contains(self) {
|
while !outer.contains(self) {
|
||||||
@@ -730,8 +735,10 @@ impl Span {
|
|||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walk down the expansion ancestors to find a span with the same [`SyntaxContext`] as
|
/// Find the first ancestor span with the same [`SyntaxContext`] as `other`.
|
||||||
/// `other`.
|
///
|
||||||
|
/// This method traverses the macro expansion ancestors until it finds a span
|
||||||
|
/// that has the same [`SyntaxContext`] as `other`.
|
||||||
///
|
///
|
||||||
/// Like [`find_ancestor_inside_same_ctxt`], but specifically for when spans might not
|
/// Like [`find_ancestor_inside_same_ctxt`], but specifically for when spans might not
|
||||||
/// overlap. Take care when using this, and prefer [`find_ancestor_inside`] or
|
/// overlap. Take care when using this, and prefer [`find_ancestor_inside`] or
|
||||||
@@ -747,9 +754,12 @@ impl Span {
|
|||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walk down the expansion ancestors to find a span that's contained within `outer` and
|
/// Find the first ancestor span that's contained within `outer` and
|
||||||
/// has the same [`SyntaxContext`] as `outer`.
|
/// has the same [`SyntaxContext`] as `outer`.
|
||||||
///
|
///
|
||||||
|
/// This method traverses the macro expansion ancestors until it finds a span
|
||||||
|
/// that is both contained within `outer` and has the same [`SyntaxContext`] as `outer`.
|
||||||
|
///
|
||||||
/// This method is the combination of [`find_ancestor_inside`] and
|
/// This method is the combination of [`find_ancestor_inside`] and
|
||||||
/// [`find_ancestor_in_same_ctxt`] and should be preferred when extending the returned span.
|
/// [`find_ancestor_in_same_ctxt`] and should be preferred when extending the returned span.
|
||||||
/// If you do not need to modify the span, use [`find_ancestor_inside`] instead.
|
/// If you do not need to modify the span, use [`find_ancestor_inside`] instead.
|
||||||
@@ -763,43 +773,43 @@ impl Span {
|
|||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively walk down the expansion ancestors to find the oldest ancestor span with the same
|
/// Find the first ancestor span that does not come from an external macro.
|
||||||
/// [`SyntaxContext`] the initial span.
|
|
||||||
///
|
///
|
||||||
/// This method is suitable for peeling through *local* macro expansions to find the "innermost"
|
/// This method traverses the macro expansion ancestors until it finds a span
|
||||||
/// span that is still local and shares the same [`SyntaxContext`]. For example, given
|
/// that is either from user-written code or from a local macro (defined in the current crate).
|
||||||
///
|
///
|
||||||
/// ```ignore (illustrative example, contains type error)
|
/// External macros are those defined in dependencies or the standard library.
|
||||||
/// macro_rules! outer {
|
/// This method is useful for reporting errors in user-controllable code and avoiding
|
||||||
/// ($x: expr) => {
|
/// diagnostics inside external macros.
|
||||||
/// inner!($x)
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
///
|
||||||
/// macro_rules! inner {
|
/// # See also
|
||||||
/// ($x: expr) => {
|
|
||||||
/// format!("error: {}", $x)
|
|
||||||
/// //~^ ERROR mismatched types
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
///
|
||||||
/// fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
|
/// - [`Self::find_ancestor_not_from_macro`]
|
||||||
/// Err(outer!(x))
|
/// - [`Self::in_external_macro`]
|
||||||
/// }
|
pub fn find_ancestor_not_from_extern_macro(mut self, sm: &SourceMap) -> Option<Span> {
|
||||||
/// ```
|
while self.in_external_macro(sm) {
|
||||||
///
|
self = self.parent_callsite()?;
|
||||||
/// 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
|
Some(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the first ancestor span that does not come from any macro expansion.
|
||||||
|
///
|
||||||
|
/// This method traverses the macro expansion ancestors until it finds a span
|
||||||
|
/// that originates from user-written code rather than any macro-generated code.
|
||||||
|
///
|
||||||
|
/// This method is useful for reporting errors at the exact location users wrote code
|
||||||
|
/// and providing suggestions at directly editable locations.
|
||||||
|
///
|
||||||
|
/// # See also
|
||||||
|
///
|
||||||
|
/// - [`Self::find_ancestor_not_from_extern_macro`]
|
||||||
|
/// - [`Span::from_expansion`]
|
||||||
|
pub fn find_ancestor_not_from_macro(mut self) -> Option<Span> {
|
||||||
|
while self.from_expansion() {
|
||||||
|
self = self.parent_callsite()?;
|
||||||
|
}
|
||||||
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Edition of the crate from which this span came.
|
/// Edition of the crate from which this span came.
|
||||||
|
|||||||
Reference in New Issue
Block a user