diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index ff7716ce7ea..bec177a2845 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -299,7 +299,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if mutbls_match { (expected, INITIAL_BM, true) } else { - (expected, def_bm, false) + let mut new_bm = def_bm; + if new_bm.0 == ByRef::Yes(Mutability::Mut) && mutbl == Mutability::Not { + new_bm.0 = ByRef::Yes(Mutability::Not); + } + (expected, new_bm, false) } } else { (expected, INITIAL_BM, mutbls_match) diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs index f8378427383..3cf6008609d 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs @@ -26,7 +26,16 @@ pub fn main() { if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { let _: u32 = x; } - if let Some(&Some(&mut x)) = &mut Some(& Some(0)) { + if let Some(&Some(&x)) = &mut Some(&Some(0)) { let _: u32 = x; } + if let Some(&Some(x)) = &mut Some(&Some(0)) { + let _: &u32 = x; + } + if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) { + let _: &u32 = x; + } + if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { + let _: &u32 = x; + } } 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 566196c1a32..f8385d2e049 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 @@ -10,4 +10,11 @@ pub fn main() { if let Some(&Some(&_)) = &Some(&mut Some(0)) { //~^ ERROR: mismatched types } + if let Some(&Some(x)) = &mut Some(&Some(0)) { + let _: &mut u32 = x; + //~^ ERROR: mismatched types + } + if let Some(&Some(&x)) = Some(&Some(&mut 0)) { + //~^ ERROR: mismatched types + } } 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 96a107b5c50..8b714cfcc3e 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 @@ -20,6 +20,32 @@ LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { = note: expected type `{integer}` found reference `&_` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:14:27 + | +LL | let _: &mut u32 = x; + | -------- ^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut u32` + found reference `&{integer}` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:17:23 + | +LL | if let Some(&Some(&x)) = Some(&Some(&mut 0)) { + | ^^ ------------------- this expression has type `Option<&Option<&mut {integer}>>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { + | ~ + +error: aborting due to 4 previous errors For more information about this 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 new file mode 100644 index 00000000000..36455488407 --- /dev/null +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs @@ -0,0 +1,11 @@ +//@ edition: 2024 +//@ compile-flags: -Zunstable-options +#![allow(incomplete_features)] +#![feature(ref_pat_eat_one_layer_2024)] + +pub fn main() { + if let Some(&Some(x)) = Some(&Some(&mut 0)) { + //~^ ERROR: cannot move out of a shared reference [E0507] + let _: &u32 = x; + } +} 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 new file mode 100644 index 00000000000..ccfb5c7a0c0 --- /dev/null +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/ref_pat_eat_one_layer_2024_fail2.rs:7:29 + | +LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { + | - ^^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | if let Some(&Some(ref x)) = Some(&Some(&mut 0)) { + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`.