about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-07-30 09:02:21 +0000
committerbors <bors@rust-lang.org>2025-07-30 09:02:21 +0000
commite5e79f8bd428d0b8d26e8240d718b134ef297459 (patch)
tree395771116faa1afd2896a964e9b81189fbe6790b /compiler
parent72716b134ac26b837703e46cbda99a453ae92c42 (diff)
parent3682d8c1ce4379b9ad7d9da655f2fefee8bb86c3 (diff)
downloadrust-e5e79f8bd428d0b8d26e8240d718b134ef297459.tar.gz
rust-e5e79f8bd428d0b8d26e8240d718b134ef297459.zip
Auto merge of #144673 - Zalathar:rollup-0kpeq3n, r=Zalathar
Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#144042 (Verify llvm-needs-components are not empty and match the --target value)
 - rust-lang/rust#144268 (Add method `find_ancestor_not_from_macro` and `find_ancestor_not_from_extern_macro` to supersede `find_oldest_ancestor_in_same_ctxt`)
 - rust-lang/rust#144411 (Remove `hello_world` directory)
 - rust-lang/rust#144662 (compiletest: Move directive names back into a separate file)
 - rust-lang/rust#144666 (Make sure to account for the right item universal regions in borrowck)
 - rust-lang/rust#144668 ([test][run-make] add needs-llvm-components)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs2
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs12
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_span/src/lib.rs82
5 files changed, 79 insertions, 48 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index a10da08ddf3..fdca6b56540 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -341,7 +341,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
                                 }
                             }
                         } 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 {
                                 // #85581: If the first mutable borrow's scope contains
                                 // the second borrow, this suggestion isn't helpful.
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index f138f265320..240c9a5223b 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -969,13 +969,28 @@ fn for_each_late_bound_region_in_item<'tcx>(
     mir_def_id: LocalDefId,
     mut f: impl FnMut(ty::Region<'tcx>),
 ) {
-    if !tcx.def_kind(mir_def_id).is_fn_like() {
-        return;
-    }
+    let bound_vars = match tcx.def_kind(mir_def_id) {
+        DefKind::Fn | DefKind::AssocFn => {
+            tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id))
+        }
+        // We extract the bound vars from the deduced closure signature, since we may have
+        // only deduced that a param in the closure signature is late-bound from a constraint
+        // that we discover during typeck.
+        DefKind::Closure => {
+            let ty = tcx.type_of(mir_def_id).instantiate_identity();
+            match *ty.kind() {
+                ty::Closure(_, args) => args.as_closure().sig().bound_vars(),
+                ty::CoroutineClosure(_, args) => {
+                    args.as_coroutine_closure().coroutine_closure_sig().bound_vars()
+                }
+                ty::Coroutine(_, _) | ty::Error(_) => return,
+                _ => unreachable!("unexpected type for closure: {ty}"),
+            }
+        }
+        _ => return,
+    };
 
-    for (idx, bound_var) in
-        tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)).iter().enumerate()
-    {
+    for (idx, bound_var) in bound_vars.iter().enumerate() {
         if let ty::BoundVariableKind::Region(kind) = bound_var {
             let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
             let liberated_region = ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), kind);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 33ae4f6c45c..2345cdab208 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1302,7 +1302,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 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(
                 span,
@@ -1395,7 +1395,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .macro_backtrace()
                 .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 {
                 vec![(span.shrink_to_hi(), ".into()".to_owned())]
@@ -2062,7 +2065,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             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);
         true
     }
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 11df071f068..00e40b515a3 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -185,7 +185,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
         let mut op_warned = false;
 
         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(
                 UNUSED_MUST_USE,
                 expr.span,
@@ -511,7 +511,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                     );
                 }
                 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(
                         UNUSED_MUST_USE,
                         span,
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index dbc67da37b5..3f72ccd9f89 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -716,12 +716,17 @@ impl Span {
         (!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,
     /// 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
     pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
         while !outer.contains(self) {
@@ -730,8 +735,10 @@ impl Span {
         Some(self)
     }
 
-    /// Walk down the expansion ancestors to find a span with the same [`SyntaxContext`] as
-    /// `other`.
+    /// Find the first ancestor span with the same [`SyntaxContext`] as `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
     /// overlap. Take care when using this, and prefer [`find_ancestor_inside`] or
@@ -747,9 +754,12 @@ impl Span {
         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`.
     ///
+    /// 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
     /// [`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.
@@ -763,43 +773,43 @@ impl Span {
         Some(self)
     }
 
-    /// Recursively walk down the expansion ancestors to find the oldest ancestor span with the same
-    /// [`SyntaxContext`] the initial span.
+    /// Find the first ancestor span that does not come from an external macro.
     ///
-    /// 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
+    /// This method traverses the macro expansion ancestors until it finds a span
+    /// that is either from user-written code or from a local macro (defined in the current crate).
     ///
-    /// ```ignore (illustrative example, contains type error)
-    ///  macro_rules! outer {
-    ///      ($x: expr) => {
-    ///          inner!($x)
-    ///      }
-    ///  }
+    /// External macros are those defined in dependencies or the standard library.
+    /// This method is useful for reporting errors in user-controllable code and avoiding
+    /// diagnostics inside external macros.
     ///
-    ///  macro_rules! inner {
-    ///      ($x: expr) => {
-    ///          format!("error: {}", $x)
-    ///          //~^ ERROR mismatched types
-    ///      }
-    ///  }
+    /// # See also
     ///
-    ///  fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
-    ///      Err(outer!(x))
-    ///  }
-    /// ```
+    /// - [`Self::find_ancestor_not_from_macro`]
+    /// - [`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()?;
+        }
+        Some(self)
+    }
+
+    /// Find the first ancestor span that does not come from any macro expansion.
     ///
-    /// 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;
+    /// 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()?;
         }
-        cur
+        Some(self)
     }
 
     /// Edition of the crate from which this span came.