about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authordianne <diannes.gm@gmail.com>2025-02-03 22:18:00 -0800
committerdianne <diannes.gm@gmail.com>2025-02-03 22:23:35 -0800
commit4331f55b729d1a41004305f85dfe4dbbcec3ee3f (patch)
treeb3ed9d2f2ac05e3c2b8b0a503f55dcfc39d96767 /compiler
parent9202001c1c5c3bd9c1fce522744c8620e17d791a (diff)
downloadrust-4331f55b729d1a41004305f85dfe4dbbcec3ee3f.tar.gz
rust-4331f55b729d1a41004305f85dfe4dbbcec3ee3f.zip
highlight the whole problem subpattern when pointing out the default binding mode
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs35
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs4
3 files changed, 28 insertions, 17 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 1970040ec86..6b0a87f1aef 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -2784,29 +2784,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // error if the subpattern is of edition >= 2024.
         let trimmed_span = subpat.span.until(cutoff_span).with_ctxt(subpat.span.ctxt());
 
+        let mut typeck_results = self.typeck_results.borrow_mut();
+        let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
+        let info = table.entry(pat_id).or_default();
+
+        info.primary_spans.push(trimmed_span);
+
         // Only provide a detailed label if the problematic subpattern isn't from an expansion.
         // In the case that it's from a macro, we'll add a more detailed note in the emitter.
-        let desc = if subpat.span.from_expansion() {
+        let from_expansion = subpat.span.from_expansion();
+        let primary_label = if from_expansion {
             // NB: This wording assumes the only expansions that can produce problematic reference
             // patterns and bindings are macros. If a desugaring or AST pass is added that can do
             // so, we may want to inspect the span's source callee or macro backtrace.
             "occurs within macro expansion"
         } else {
-            match def_br_mutbl {
-                Mutability::Not => "default binding mode is `ref`",
-                Mutability::Mut => "default binding mode is `ref mut`",
+            if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) {
+                info.bad_modifiers |= true;
+                "this binding modifier"
+            } else {
+                info.bad_ref_pats |= true;
+                "this reference pattern"
             }
         };
+        info.span_labels.push((trimmed_span, primary_label.to_owned()));
 
-        let mut typeck_results = self.typeck_results.borrow_mut();
-        let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
-        let info = table.entry(pat_id).or_default();
-
-        info.labels.push((trimmed_span, desc.to_owned()));
-        if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) {
-            info.bad_modifiers |= true;
-        } else {
-            info.bad_ref_pats |= true;
+        if !from_expansion {
+            // Add a secondary label covering the whole pattern noting the default binding mode
+            let def_br_desc = match def_br_mutbl {
+                Mutability::Not => "default binding mode is `ref`",
+                Mutability::Mut => "default binding mode is `ref mut`",
+            };
+            info.span_labels.push((subpat.span, def_br_desc.to_owned()));
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 0dbbfee0cfa..a75a7fcd569 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -816,8 +816,10 @@ impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> {
 /// emitted during THIR construction.
 #[derive(TyEncodable, TyDecodable, Debug, HashStable, Default)]
 pub struct Rust2024IncompatiblePatInfo {
-    /// Labels for subpatterns incompatible with Rust 2024.
-    pub labels: Vec<(Span, String)>,
+    /// Spans for `&`s, `&mut`s, and binding modifiers incompatible with Rust 2024.
+    pub primary_spans: Vec<Span>,
+    /// Labels for the primary spans and their patterns, to provide additional context.
+    pub span_labels: Vec<(Span, String)>,
     /// Whether any binding modifiers occur under a non-`move` default binding mode.
     pub bad_modifiers: bool,
     /// Whether any `&` or `&mut` patterns occur under a non-`move` default binding mode.
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index f12234723ec..cdabd283150 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -59,8 +59,8 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
     debug!("pat_from_hir({:?}) = {:?}", pat, result);
     if let Some(info) = migration_info {
         let sugg = pcx.rust_2024_migration_suggestion.expect("suggestion should be present");
-        let mut spans = MultiSpan::from_spans(info.labels.iter().map(|(span, _)| *span).collect());
-        for (span, label) in &info.labels {
+        let mut spans = MultiSpan::from_spans(info.primary_spans.clone());
+        for (span, label) in &info.span_labels {
             spans.push_span_label(*span, label.clone());
         }
         // If a relevant span is from at least edition 2024, this is a hard error.