diff options
5 files changed, 151 insertions, 179 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 47175cda63b..be72af63fe5 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -235,6 +235,9 @@ enum InheritedRefMatchRule { /// Whether to allow reference patterns to consume only an inherited reference when matching /// against a non-reference type. This is `false` for stable Rust. eat_inherited_ref_alone: bool, + /// Whether to allow a `&mut` reference pattern to eat a `&` reference type if it's also + /// able to consume a mutable inherited reference. This is `false` for stable Rust. + fallback_to_outer: bool, }, } @@ -261,12 +264,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { // Currently, matching against an inherited ref on edition 2024 is an error. // Use `EatBoth` as a fallback to be similar to stable Rust. - InheritedRefMatchRule::EatBoth { eat_inherited_ref_alone: false } + InheritedRefMatchRule::EatBoth { + eat_inherited_ref_alone: false, + fallback_to_outer: false, + } } } else { + let has_structural_gate = self.tcx.features().ref_pat_eat_one_layer_2024_structural(); InheritedRefMatchRule::EatBoth { - eat_inherited_ref_alone: self.tcx.features().ref_pat_eat_one_layer_2024() - || self.tcx.features().ref_pat_eat_one_layer_2024_structural(), + eat_inherited_ref_alone: has_structural_gate + || self.tcx.features().ref_pat_eat_one_layer_2024(), + fallback_to_outer: has_structural_gate, } } } @@ -2386,12 +2394,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return expected; } } - InheritedRefMatchRule::EatBoth { eat_inherited_ref_alone: true } => { + InheritedRefMatchRule::EatBoth { + eat_inherited_ref_alone: true, + fallback_to_outer, + } => { // Reset binding mode on old editions pat_info.binding_mode = ByRef::No; - if let ty::Ref(_, _, _) = *expected.kind() { + if let ty::Ref(_, inner_ty, _) = *expected.kind() { // Consume both the inherited and inner references. + if fallback_to_outer && inh_mut.is_mut() { + // If we can fall back to matching the inherited reference, the expected + // type is a reference type (of any mutability), and the inherited + // reference is mutable, we'll always be able to match. We handle that + // here to avoid adding fallback-to-outer to the common logic below. + // NB: This way of phrasing the logic will catch more cases than those + // that need to fall back to matching the inherited reference. However, + // as long as `&` patterns can match mutable (inherited) references + // (RFC 3627, Rule 5) this should be sound. + debug_assert!(ref_pat_matches_mut_ref); + self.check_pat(inner, inner_ty, pat_info); + return expected; + } else { + // Otherwise, use the common logic below for matching the inner + // reference type. + } } else { // The expected type isn't a reference type, so only match against the // inherited reference. @@ -2405,9 +2432,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return expected; } } - InheritedRefMatchRule::EatBoth { eat_inherited_ref_alone: false } => { + rule @ InheritedRefMatchRule::EatBoth { + eat_inherited_ref_alone: false, + fallback_to_outer, + } => { // Reset binding mode on stable Rust. This will be a type error below if // `expected` is not a reference type. + debug_assert!(!fallback_to_outer, "typing rule `{rule:?}` is unimplemented."); pat_info.binding_mode = ByRef::No; self.add_rust_2024_migration_desugared_pat( pat_info.top_info.hir_id, diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr index f784d7e9988..086d4bb133b 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr @@ -105,28 +105,7 @@ LL + let [ref x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:108:10 - | -LL | let [&mut ref mut x] = &mut [&0]; - | ^^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability - | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:108:10 - | -LL | let [&mut ref mut x] = &mut [&0]; - | ^^^^^^^^^^^^^^ -help: consider removing `&mut` from the pattern - | -LL - let [&mut ref mut x] = &mut [&0]; -LL + let [ref mut x] = &mut [&0]; - | - -error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:114:10 + --> $DIR/well-typed-edition-2024.rs:117:10 | LL | let [&mut mut x] = &mut [&0]; | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -136,7 +115,7 @@ LL | let [&mut mut x] = &mut [&0]; = note: expected reference `&{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:114:10 + --> $DIR/well-typed-edition-2024.rs:117:10 | LL | let [&mut mut x] = &mut [&0]; | ^^^^^^^^^^ @@ -147,7 +126,7 @@ LL + let [mut x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:120:10 + --> $DIR/well-typed-edition-2024.rs:123:10 | LL | let [&mut &x] = &mut [&0]; | ^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -158,7 +137,7 @@ LL | let [&mut &x] = &mut [&0]; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:126:10 + --> $DIR/well-typed-edition-2024.rs:129:10 | LL | let [&mut &ref x] = &mut [&0]; | ^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -169,7 +148,7 @@ LL | let [&mut &ref x] = &mut [&0]; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:132:10 + --> $DIR/well-typed-edition-2024.rs:135:10 | LL | let [&mut &(mut x)] = &mut [&0]; | ^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -179,6 +158,27 @@ LL | let [&mut &(mut x)] = &mut [&0]; = note: expected reference `&{integer}` found mutable reference `&mut _` +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:109:14 + | +LL | let [&mut ref mut x] = &mut [&0]; + | ^^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:109:14 + | +LL | let [&mut ref mut x] = &mut [&0]; + | ^^^^^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut ref mut x] = &mut [&0]; +LL + let [ref mut x] = &mut [&0]; + | + error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs index 851011918fe..63a09fe90c9 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs @@ -91,47 +91,50 @@ pub fn main() { #[cfg(any(classic2024, structural2024))] let _: u32 = x; } - // Tests for eat-inner rulesets matching on the outer reference if matching on the inner - // reference causes a mutability mismatch, i.e. `Deref(EatInner, FallbackToOuter)`: + // Tests for eat-inner and eat-both rulesets matching on the outer reference if matching on the + // inner reference causes a mutability mismatch. i.e. tests for "fallback-to-outer" deref rules. let [&mut x] = &mut [&0]; - //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021,structural2021]~| types differ in mutability - // TODO: on `structural2021` `x` should have type `u32` + //[stable2021,classic2021]~^ mismatched types + //[stable2021,classic2021]~| types differ in mutability + #[cfg(structural2021)] let _: u32 = x; #[cfg(any(classic2024, structural2024))] let _: &u32 = x; let [&mut ref x] = &mut [&0]; - //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021,structural2021]~| types differ in mutability - // TODO: on `structural2021` `x` should have type `&u32` + //[stable2021,classic2021]~^ mismatched types + //[stable2021,classic2021]~| types differ in mutability + #[cfg(structural2021)] let _: &u32 = x; #[cfg(any(classic2024, structural2024))] let _: &&u32 = x; - let [&mut ref mut x] = &mut [&0]; - //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021,structural2021]~| types differ in mutability - // TODO: this should be a mut borrow behind shared borrow error on `structural2021` - #[cfg(any(classic2024, structural2024))] let _: &mut &u32 = x; + fn borrowck_error_on_structural2021() { + let [&mut ref mut x] = &mut [&0]; + //[stable2021,classic2021]~^ mismatched types + //[stable2021,classic2021]~| types differ in mutability + //[structural2021]~^^^ cannot borrow data in a `&` reference as mutable + #[cfg(any(classic2024, structural2024))] let _: &mut &u32 = x; + } + borrowck_error_on_structural2021(); let [&mut mut x] = &mut [&0]; - //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021,structural2021]~| types differ in mutability - // TODO: on `structural2021` `x` should have type `u32` + //[stable2021,classic2021]~^ mismatched types + //[stable2021,classic2021]~| types differ in mutability + #[cfg(structural2021)] let _: u32 = x; #[cfg(any(classic2024, structural2024))] let _: &u32 = x; let [&mut &x] = &mut [&0]; //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021,structural2021]~| types differ in mutability - // TODO: [structural2021]~| expected integer, found `&_` + //[stable2021,classic2021]~| types differ in mutability + //[structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; let [&mut &ref x] = &mut [&0]; //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021,structural2021]~| types differ in mutability - // TODO: [structural2021]~| expected integer, found `&_` + //[stable2021,classic2021]~| types differ in mutability + //[structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: &u32 = x; let [&mut &(mut x)] = &mut [&0]; //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021,structural2021]~| types differ in mutability - // TODO: [structural2021]~| expected integer, found `&_` + //[stable2021,classic2021]~| types differ in mutability + //[structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr index fb99e3983e8..adb47172f34 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr @@ -186,28 +186,7 @@ LL + let [ref x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:108:10 - | -LL | let [&mut ref mut x] = &mut [&0]; - | ^^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability - | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:108:10 - | -LL | let [&mut ref mut x] = &mut [&0]; - | ^^^^^^^^^^^^^^ -help: consider removing `&mut` from the pattern - | -LL - let [&mut ref mut x] = &mut [&0]; -LL + let [ref mut x] = &mut [&0]; - | - -error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:114:10 + --> $DIR/well-typed-edition-2024.rs:117:10 | LL | let [&mut mut x] = &mut [&0]; | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -217,7 +196,7 @@ LL | let [&mut mut x] = &mut [&0]; = note: expected reference `&{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:114:10 + --> $DIR/well-typed-edition-2024.rs:117:10 | LL | let [&mut mut x] = &mut [&0]; | ^^^^^^^^^^ @@ -228,7 +207,7 @@ LL + let [mut x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:120:10 + --> $DIR/well-typed-edition-2024.rs:123:10 | LL | let [&mut &x] = &mut [&0]; | ^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -239,7 +218,7 @@ LL | let [&mut &x] = &mut [&0]; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:126:10 + --> $DIR/well-typed-edition-2024.rs:129:10 | LL | let [&mut &ref x] = &mut [&0]; | ^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -250,7 +229,7 @@ LL | let [&mut &ref x] = &mut [&0]; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:132:10 + --> $DIR/well-typed-edition-2024.rs:135:10 | LL | let [&mut &(mut x)] = &mut [&0]; | ^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -260,6 +239,27 @@ LL | let [&mut &(mut x)] = &mut [&0]; = note: expected reference `&{integer}` found mutable reference `&mut _` +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:109:14 + | +LL | let [&mut ref mut x] = &mut [&0]; + | ^^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:109:14 + | +LL | let [&mut ref mut x] = &mut [&0]; + | ^^^^^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut ref mut x] = &mut [&0]; +LL + let [ref mut x] = &mut [&0]; + | + error: aborting due to 17 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr index f784d7e9988..f8c2bd9a921 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr @@ -63,122 +63,60 @@ LL + if let Some(&Some(x)) = &mut Some(&Some(0)) { | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:96:10 + --> $DIR/well-typed-edition-2024.rs:123:15 | -LL | let [&mut x] = &mut [&0]; - | ^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability - | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:96:10 - | -LL | let [&mut x] = &mut [&0]; - | ^^^^^^ -help: consider removing `&mut` from the pattern - | -LL - let [&mut x] = &mut [&0]; -LL + let [x] = &mut [&0]; - | - -error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:102:10 - | -LL | let [&mut ref x] = &mut [&0]; - | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability - | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:102:10 - | -LL | let [&mut ref x] = &mut [&0]; - | ^^^^^^^^^^ -help: consider removing `&mut` from the pattern - | -LL - let [&mut ref x] = &mut [&0]; -LL + let [ref x] = &mut [&0]; - | - -error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:108:10 - | -LL | let [&mut ref mut x] = &mut [&0]; - | ^^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability - | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:108:10 +LL | let [&mut &x] = &mut [&0]; + | ^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | expected integer, found `&_` | -LL | let [&mut ref mut x] = &mut [&0]; - | ^^^^^^^^^^^^^^ -help: consider removing `&mut` from the pattern + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern | -LL - let [&mut ref mut x] = &mut [&0]; -LL + let [ref mut x] = &mut [&0]; +LL - let [&mut &x] = &mut [&0]; +LL + let [&mut x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:114:10 - | -LL | let [&mut mut x] = &mut [&0]; - | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability + --> $DIR/well-typed-edition-2024.rs:129:15 | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:114:10 +LL | let [&mut &ref x] = &mut [&0]; + | ^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | expected integer, found `&_` | -LL | let [&mut mut x] = &mut [&0]; - | ^^^^^^^^^^ -help: consider removing `&mut` from the pattern + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern | -LL - let [&mut mut x] = &mut [&0]; -LL + let [mut x] = &mut [&0]; +LL - let [&mut &ref x] = &mut [&0]; +LL + let [&mut ref x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:120:10 + --> $DIR/well-typed-edition-2024.rs:135:15 | -LL | let [&mut &x] = &mut [&0]; - | ^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability +LL | let [&mut &(mut x)] = &mut [&0]; + | ^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | expected integer, found `&_` | - = note: expected reference `&{integer}` - found mutable reference `&mut _` - -error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:126:10 + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern | -LL | let [&mut &ref x] = &mut [&0]; - | ^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability +LL - let [&mut &(mut x)] = &mut [&0]; +LL + let [&mut mut x)] = &mut [&0]; | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:132:10 - | -LL | let [&mut &(mut x)] = &mut [&0]; - | ^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/well-typed-edition-2024.rs:109:19 | - = note: expected reference `&{integer}` - found mutable reference `&mut _` +LL | let [&mut ref mut x] = &mut [&0]; + | ^^^^^^^^^ cannot borrow as mutable -error: aborting due to 11 previous errors +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0596. +For more information about an error, try `rustc --explain E0308`. |
