about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJules Bertholet <julesbertholet@quoi.xyz>2024-05-04 14:57:27 -0400
committerJules Bertholet <julesbertholet@quoi.xyz>2024-05-10 13:47:36 -0400
commited96c655c6e147f5c2ce54e91f71a0874f9f836a (patch)
tree02705d562fb819f06d386a3929d3ff8510c0164b
parent4f76f1069af505ce72535bda8d10e44dd81e65a5 (diff)
downloadrust-ed96c655c6e147f5c2ce54e91f71a0874f9f836a.tar.gz
rust-ed96c655c6e147f5c2ce54e91f71a0874f9f836a.zip
Various fixes:
- Only show error when move-check would not be triggered
- Add structured suggestion
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs44
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs12
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr39
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs3
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr11
5 files changed, 71 insertions, 38 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 99653814d6f..f1eceed0ac8 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -163,7 +163,13 @@ enum MutblCap {
 
 impl MutblCap {
     fn cap_mutbl_to_not(self, span: Option<Span>) -> Self {
-        if self == MutblCap::Mut { MutblCap::Not(span) } else { self }
+        if let Some(s) = span
+            && self != MutblCap::Not(None)
+        {
+            MutblCap::Not(Some(s))
+        } else {
+            MutblCap::Not(None)
+        }
     }
 
     fn as_mutbl(self) -> Mutability {
@@ -744,9 +750,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.tcx.dcx(),
                 ident.span,
                 E0596,
-                "cannot bind with `ref mut` behind an `&` pattern"
+                "cannot borrow as mutable inside an `&` pattern"
+            );
+            err.span_suggestion(
+                and_pat_span,
+                "replace this `&` with `&mut`",
+                "&mut ",
+                Applicability::MachineApplicable,
             );
-            err.span_help(and_pat_span, "change this `&` pattern to an `&mut`");
             err.emit();
         }
 
@@ -2187,7 +2198,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // the bad interactions of the given hack detailed in (note_1).
                     debug!("check_pat_ref: expected={:?}", expected);
                     match *expected.kind() {
-                        ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty, pat_info),
+                        ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
+                            let pat_info = if r_mutbl == Mutability::Not
+                                && ((pat.span.at_least_rust_2024()
+                                    && self.tcx.features().ref_pat_eat_one_layer_2024)
+                                    || self.tcx.features().ref_pat_everywhere)
+                            {
+                                PatInfo {
+                                    max_ref_mutbl: pat_info.max_ref_mutbl.cap_mutbl_to_not(None),
+                                    ..pat_info
+                                }
+                            } else {
+                                pat_info
+                            };
+                            (expected, r_ty, pat_info)
+                        }
 
                         // `&` pattern eats `&mut` reference
                         ty::Ref(_, r_ty, Mutability::Mut)
@@ -2196,16 +2221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     && self.tcx.features().ref_pat_eat_one_layer_2024)
                                     || self.tcx.features().ref_pat_everywhere) =>
                         {
-                            (
-                                expected,
-                                r_ty,
-                                PatInfo {
-                                    max_ref_mutbl: pat_info
-                                        .max_ref_mutbl
-                                        .cap_mutbl_to_not(Some(pat.span.until(inner.span))),
-                                    ..pat_info
-                                },
-                            )
+                            (expected, r_ty, pat_info)
                         }
 
                         _ if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere => {
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
index 61e61719458..376855406a6 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
@@ -24,18 +24,24 @@ pub fn main() {
         //~^ ERROR: mismatched types
     }
     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
-        //~^ ERROR: cannot bind with `ref mut` behind an `&` pattern
+        //~^ ERROR: cannot borrow as mutable inside an `&` pattern
     }
     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
-        //~^ ERROR: cannot bind with `ref mut` behind an `&` pattern
+        //~^ ERROR: cannot borrow as mutable inside an `&` pattern
     }
     if let Some(&mut Some(x)) = &Some(Some(0)) {
         //~^ ERROR: mismatched types
     }
 
-    let &mut _= &&0;
+    let &mut _ = &&0;
     //~^ ERROR: mismatched types
 
     let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
     //~^ ERROR: mismatched types
+
+    macro_rules! pat {
+        ($var:ident) => { ref mut $var };
+    }
+    let &pat!(x) = &mut 0;
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
 }
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
index 2aa2e2851ce..0512a31011d 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
@@ -64,29 +64,21 @@ LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
    = note:           expected enum `Option<{integer}>`
            found mutable reference `&mut _`
 
-error[E0596]: cannot bind with `ref mut` behind an `&` pattern
+error[E0596]: cannot borrow as mutable inside an `&` pattern
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:31
    |
 LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
-   |                               ^
-   |
-help: change this `&` pattern to an `&mut`
-  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17
-   |
-LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
-   |                 ^
+   |                 -             ^
+   |                 |
+   |                 help: replace this `&` with `&mut`: `&mut`
 
-error[E0596]: cannot bind with `ref mut` behind an `&` pattern
+error[E0596]: cannot borrow as mutable inside an `&` pattern
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:29:31
    |
 LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
-   |                               ^
-   |
-help: change this `&` pattern to an `&mut`
-  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:29:12
-   |
-LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
-   |            ^
+   |            -                  ^
+   |            |
+   |            help: replace this `&` with `&mut`: `&mut`
 
 error[E0308]: mismatched types
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:17
@@ -102,8 +94,8 @@ LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
 error[E0308]: mismatched types
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:36:9
    |
-LL |     let &mut _= &&0;
-   |         ^^^^^^  --- this expression has type `&&{integer}`
+LL |     let &mut _ = &&0;
+   |         ^^^^^^   --- this expression has type `&&{integer}`
    |         |
    |         expected integer, found `&mut _`
    |
@@ -121,7 +113,16 @@ LL |     let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 
-error: aborting due to 11 previous errors
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:45:15
+   |
+LL |         ($var:ident) => { ref mut $var };
+   |                           ------------ help: replace this `&` with `&mut`: `&mut`
+LL |     }
+LL |     let &pat!(x) = &mut 0;
+   |               ^
+
+error: aborting due to 12 previous errors
 
 Some errors have detailed explanations: E0308, E0596.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
index 36455488407..3cdf47c1dbf 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
@@ -8,4 +8,7 @@ pub fn main() {
         //~^ ERROR: cannot move out of a shared reference [E0507]
         let _: &u32 = x;
     }
+
+    let &ref mut x = &0;
+    //~^ cannot borrow data in a `&` reference as mutable [E0596]
 }
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
index ccfb5c7a0c0..8b86fa65c4d 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
@@ -12,6 +12,13 @@ help: consider borrowing the pattern binding
 LL |     if let Some(&Some(ref x)) = Some(&Some(&mut 0)) {
    |                       +++
 
-error: aborting due to 1 previous error
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/ref_pat_eat_one_layer_2024_fail2.rs:12:10
+   |
+LL |     let &ref mut x = &0;
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0507`.
+Some errors have detailed explanations: E0507, E0596.
+For more information about an error, try `rustc --explain E0507`.