From 4606485d0c36676f08a61c524dbc2ee05bbfb049 Mon Sep 17 00:00:00 2001 From: "许杰友 Jieyou Xu (Joe)" Date: Mon, 8 Apr 2024 21:42:06 +0000 Subject: typeck: fix `?` operator suggestion span --- compiler/rustc_span/src/lib.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'compiler/rustc_span/src') diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 7ce879807ca..c1e1175b4bd 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -743,6 +743,45 @@ impl Span { 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> { + /// 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. pub fn edition(self) -> edition::Edition { self.ctxt().edition() -- cgit 1.4.1-3-g733a5