diff options
4 files changed, 73 insertions, 145 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 1e28571807e..4201ef66741 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -232,12 +232,13 @@ enum InheritedRefMatchRule { /// When the underlying type is a reference type, reference patterns consume both layers of /// reference, i.e. they both reset the binding mode and consume the reference type. EatBoth { - /// 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, + /// This represents two behaviors implemented by both the `ref_pat_eat_one_layer_2024` and + /// `ref_pat_eat_one_layer_2024_structural` feature gates, and is false for stable Rust. + /// - Whether to allow reference patterns to consume only an inherited reference when + /// matching against a non-reference type. + /// - Whether to allow a `&mut` reference pattern to eat a `&` reference type if it's also + /// able to consume a mutable inherited reference. + consider_inherited_ref_first: bool, }, } @@ -264,17 +265,12 @@ 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, - fallback_to_outer: false, - } + InheritedRefMatchRule::EatBoth { consider_inherited_ref_first: false } } } else { - let has_structural_gate = self.tcx.features().ref_pat_eat_one_layer_2024_structural(); InheritedRefMatchRule::EatBoth { - eat_inherited_ref_alone: has_structural_gate - || self.tcx.features().ref_pat_eat_one_layer_2024(), - fallback_to_outer: has_structural_gate, + consider_inherited_ref_first: self.tcx.features().ref_pat_eat_one_layer_2024() + || self.tcx.features().ref_pat_eat_one_layer_2024_structural(), } } } @@ -2398,20 +2394,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return expected; } } - InheritedRefMatchRule::EatBoth { - eat_inherited_ref_alone: true, - fallback_to_outer, - } => { + InheritedRefMatchRule::EatBoth { consider_inherited_ref_first: true } => { // Reset binding mode on old editions pat_info.binding_mode = ByRef::No; 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. + if inh_mut.is_mut() { + // If the expected type is a reference type (of any mutability) and the + // inherited ref is mutable, we'll be able to match, since we can fall + // back to matching the inherited ref if the real reference isn't + // mutable enough for our pattern. 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 @@ -2440,13 +2434,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return expected; } } - rule @ InheritedRefMatchRule::EatBoth { - eat_inherited_ref_alone: false, - fallback_to_outer, - } => { + InheritedRefMatchRule::EatBoth { consider_inherited_ref_first: false } => { // 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/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md index 58d8d290503..0c90cec0dbd 100644 --- a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md +++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md @@ -16,5 +16,5 @@ For more information, see the corresponding typing rules for [Editions 2021 and For alternative experimental match ergonomics, see the feature [`ref_pat_eat_one_layer_2024_structural`](./ref-pat-eat-one-layer-2024-structural.md). -[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQABAQABAAAAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false +[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQABAAAAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false [Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAAABAQABAgIAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false 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 086d4bb133b..f8c2bd9a921 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 @@ -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:117:10 - | -LL | let [&mut 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:117:10 +LL | let [&mut &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 &x] = &mut [&0]; +LL + let [&mut x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:123:10 + --> $DIR/well-typed-edition-2024.rs:129:15 | -LL | let [&mut &x] = &mut [&0]; - | ^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability +LL | let [&mut &ref 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:129: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 &ref x] = &mut [&0]; +LL + let [&mut ref x] = &mut [&0]; | - = note: expected reference `&{integer}` - found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:135:10 + --> $DIR/well-typed-edition-2024.rs:135:15 | LL | let [&mut &(mut x)] = &mut [&0]; - | ^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` - | | - | types differ in mutability + | ^^^^^^^^ --------- 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:109:14 + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern | -LL | let [&mut ref mut 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 _` -note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:109:14 + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/well-typed-edition-2024.rs:109:19 | 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]; - | + | ^^^^^^^^^ 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`. 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 63a09fe90c9..62c1c28022b 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 @@ -94,47 +94,47 @@ pub fn main() { // 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]~^ mismatched types - //[stable2021,classic2021]~| types differ in mutability - #[cfg(structural2021)] let _: u32 = x; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + #[cfg(any(classic2021, structural2021))] let _: u32 = x; #[cfg(any(classic2024, structural2024))] let _: &u32 = x; let [&mut ref x] = &mut [&0]; - //[stable2021,classic2021]~^ mismatched types - //[stable2021,classic2021]~| types differ in mutability - #[cfg(structural2021)] let _: &u32 = x; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + #[cfg(any(classic2021, structural2021))] let _: &u32 = x; #[cfg(any(classic2024, structural2024))] let _: &&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 + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + //[classic2021,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]~^ mismatched types - //[stable2021,classic2021]~| types differ in mutability - #[cfg(structural2021)] let _: u32 = x; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + #[cfg(any(classic2021, structural2021))] let _: u32 = x; #[cfg(any(classic2024, structural2024))] let _: &u32 = x; let [&mut &x] = &mut [&0]; //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021]~| types differ in mutability - //[structural2021]~| expected integer, found `&_` + //[stable2021]~| types differ in mutability + //[classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; let [&mut &ref x] = &mut [&0]; //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021]~| types differ in mutability - //[structural2021]~| expected integer, found `&_` + //[stable2021]~| types differ in mutability + //[classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: &u32 = x; let [&mut &(mut x)] = &mut [&0]; //[stable2021,classic2021,structural2021]~^ mismatched types - //[stable2021,classic2021]~| types differ in mutability - //[structural2021]~| expected integer, found `&_` + //[stable2021]~| types differ in mutability + //[classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; } |
