summary refs log tree commit diff
diff options
context:
space:
mode:
authordianne <diannes.gm@gmail.com>2025-02-03 22:18:00 -0800
committerdianne <diannes.gm@gmail.com>2025-02-10 23:21:22 -0800
commit2ee601ced63c639bf2d84a9495203821b2a48991 (patch)
tree3a978e6bbd0065a5474964492f7ef587179378aa
parentf8b23cdb75644c182711a6a198ea5adf2fb67c88 (diff)
downloadrust-2ee601ced63c639bf2d84a9495203821b2a48991.tar.gz
rust-2ee601ced63c639bf2d84a9495203821b2a48991.zip
highlight the whole problem subpattern when pointing out the default binding mode
(cherry picked from commit 4331f55b729d1a41004305f85dfe4dbbcec3ee3f)
-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
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr94
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr35
5 files changed, 129 insertions, 45 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 7059a733663..50ad0426b63 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -2649,29 +2649,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 1493bef00f8..a35c880120b 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.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
index 0a9d2cf223a..cbb94a52878 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
@@ -2,7 +2,10 @@ error: binding modifiers may only be written when the default binding mode is `m
   --> $DIR/migration_lint.rs:25:13
    |
 LL |     let Foo(mut x) = &Foo(0);
-   |             ^^^ default binding mode is `ref`
+   |             ^^^--
+   |             |
+   |             this binding modifier
+   |             default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -20,7 +23,10 @@ error: binding modifiers may only be written when the default binding mode is `m
   --> $DIR/migration_lint.rs:30:13
    |
 LL |     let Foo(mut x) = &mut Foo(0);
-   |             ^^^ default binding mode is `ref mut`
+   |             ^^^--
+   |             |
+   |             this binding modifier
+   |             default binding mode is `ref mut`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -33,7 +39,10 @@ error: binding modifiers may only be written when the default binding mode is `m
   --> $DIR/migration_lint.rs:35:13
    |
 LL |     let Foo(ref x) = &Foo(0);
-   |             ^^^ default binding mode is `ref`
+   |             ^^^--
+   |             |
+   |             this binding modifier
+   |             default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -46,7 +55,10 @@ error: binding modifiers may only be written when the default binding mode is `m
   --> $DIR/migration_lint.rs:40:13
    |
 LL |     let Foo(ref x) = &mut Foo(0);
-   |             ^^^ default binding mode is `ref mut`
+   |             ^^^--
+   |             |
+   |             this binding modifier
+   |             default binding mode is `ref mut`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -59,7 +71,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:57:13
    |
 LL |     let Foo(&x) = &Foo(&0);
-   |             ^ default binding mode is `ref`
+   |             ^-
+   |             |
+   |             this reference pattern
+   |             default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -72,7 +87,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:62:13
    |
 LL |     let Foo(&mut x) = &Foo(&mut 0);
-   |             ^^^^ default binding mode is `ref`
+   |             ^^^^--
+   |             |
+   |             this reference pattern
+   |             default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -85,7 +103,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:67:13
    |
 LL |     let Foo(&x) = &mut Foo(&0);
-   |             ^ default binding mode is `ref mut`
+   |             ^-
+   |             |
+   |             this reference pattern
+   |             default binding mode is `ref mut`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -98,7 +119,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:72:13
    |
 LL |     let Foo(&mut x) = &mut Foo(&mut 0);
-   |             ^^^^ default binding mode is `ref mut`
+   |             ^^^^--
+   |             |
+   |             this reference pattern
+   |             default binding mode is `ref mut`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -111,7 +135,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:81:17
    |
 LL |     if let Some(&x) = &&&&&Some(&0u8) {
-   |                 ^ default binding mode is `ref`
+   |                 ^-
+   |                 |
+   |                 this reference pattern
+   |                 default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -124,7 +151,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:87:17
    |
 LL |     if let Some(&mut x) = &&&&&Some(&mut 0u8) {
-   |                 ^^^^ default binding mode is `ref`
+   |                 ^^^^--
+   |                 |
+   |                 this reference pattern
+   |                 default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -137,7 +167,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:93:17
    |
 LL |     if let Some(&x) = &&&&&mut Some(&0u8) {
-   |                 ^ default binding mode is `ref`
+   |                 ^-
+   |                 |
+   |                 this reference pattern
+   |                 default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -150,7 +183,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:99:17
    |
 LL |     if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) {
-   |                 ^^^^ default binding mode is `ref mut`
+   |                 ^^^^--------------
+   |                 |
+   |                 this reference pattern
+   |                 default binding mode is `ref mut`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -163,7 +199,10 @@ error: binding modifiers may only be written when the default binding mode is `m
   --> $DIR/migration_lint.rs:111:21
    |
 LL |     let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 };
-   |                     ^^^ default binding mode is `ref`
+   |                     ^^^--
+   |                     |
+   |                     this binding modifier
+   |                     default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -176,8 +215,11 @@ error: binding modifiers and reference patterns may only be written when the def
   --> $DIR/migration_lint.rs:117:21
    |
 LL |     let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 };
-   |                     ^      ^^^ default binding mode is `ref`
-   |                     |
+   |                     ^-     ^^^--
+   |                     |      |
+   |                     |      this binding modifier
+   |                     |      default binding mode is `ref`
+   |                     this reference pattern
    |                     default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
@@ -191,8 +233,11 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:124:24
    |
 LL |     if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } =
-   |                        ^                 ^ default binding mode is `ref`
-   |                        |
+   |                        ^-------          ^-
+   |                        |                 |
+   |                        |                 this reference pattern
+   |                        |                 default binding mode is `ref`
+   |                        this reference pattern
    |                        default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
@@ -206,8 +251,9 @@ error: binding modifiers may only be written when the default binding mode is `m
   --> $DIR/migration_lint.rs:137:15
    |
 LL |         (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
-   |               ^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion
+   |               ^^^--   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion
    |               |
+   |               this binding modifier
    |               default binding mode is `ref`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -221,8 +267,11 @@ error: binding modifiers and reference patterns may only be written when the def
   --> $DIR/migration_lint.rs:145:10
    |
 LL |     let [&mut [ref a]] = &mut [&mut &[0]];
-   |          ^^^^  ^^^ default binding mode is `ref`
-   |          |
+   |          ^^^^--^^^---
+   |          |     |
+   |          |     this binding modifier
+   |          |     default binding mode is `ref`
+   |          this reference pattern
    |          default binding mode is `ref mut`
    |
    = warning: this changes meaning in Rust 2024
@@ -236,7 +285,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/migration_lint.rs:150:10
    |
 LL |     let [&(_)] = &[&0];
-   |          ^^ default binding mode is `ref`
+   |          ^^--
+   |          |
+   |          this reference pattern
+   |          default binding mode is `ref`
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr
index 89868a1f333..ce93199b186 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr
@@ -103,7 +103,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/min_match_ergonomics_fail.rs:24:20
    |
 LL | test_pat_on_type![(&x,): &(&T,)];
-   |                    ^ default binding mode is `ref`
+   |                    ^-
+   |                    |
+   |                    this reference pattern
+   |                    default binding mode is `ref`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 help: make the implied reference pattern explicit
@@ -115,7 +118,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/min_match_ergonomics_fail.rs:27:20
    |
 LL | test_pat_on_type![(&mut x,): &(&mut T,)];
-   |                    ^^^^ default binding mode is `ref`
+   |                    ^^^^--
+   |                    |
+   |                    this reference pattern
+   |                    default binding mode is `ref`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 help: make the implied reference pattern explicit
@@ -127,7 +133,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/min_match_ergonomics_fail.rs:31:28
    |
 LL | test_pat_on_type![Foo { f: &(x,) }: &Foo];
-   |                            ^ default binding mode is `ref`
+   |                            ^----
+   |                            |
+   |                            this reference pattern
+   |                            default binding mode is `ref`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 help: make the implied reference pattern explicit
@@ -139,7 +148,10 @@ error: binding modifiers may only be written when the default binding mode is `m
   --> $DIR/min_match_ergonomics_fail.rs:32:20
    |
 LL | test_pat_on_type![(mut x,): &(T,)];
-   |                    ^^^ default binding mode is `ref`
+   |                    ^^^--
+   |                    |
+   |                    this binding modifier
+   |                    default binding mode is `ref`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 help: make the implied reference pattern explicit
@@ -151,7 +163,10 @@ error: binding modifiers may only be written when the default binding mode is `m
   --> $DIR/min_match_ergonomics_fail.rs:33:20
    |
 LL | test_pat_on_type![(ref x,): &(T,)];
-   |                    ^^^ default binding mode is `ref`
+   |                    ^^^--
+   |                    |
+   |                    this binding modifier
+   |                    default binding mode is `ref`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 help: make the implied reference pattern explicit
@@ -163,7 +178,10 @@ error: binding modifiers may only be written when the default binding mode is `m
   --> $DIR/min_match_ergonomics_fail.rs:34:20
    |
 LL | test_pat_on_type![(ref mut x,): &mut (T,)];
-   |                    ^^^^^^^ default binding mode is `ref mut`
+   |                    ^^^^^^^--
+   |                    |
+   |                    this binding modifier
+   |                    default binding mode is `ref mut`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 help: make the implied reference pattern explicit
@@ -175,7 +193,10 @@ error: reference patterns may only be written when the default binding mode is `
   --> $DIR/min_match_ergonomics_fail.rs:43:10
    |
 LL |         (&x,) => x,
-   |          ^ default binding mode is `ref`
+   |          ^-
+   |          |
+   |          this reference pattern
+   |          default binding mode is `ref`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 help: make the implied reference pattern explicit