mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-01 04:27:38 +00:00
"classic2021" ruleset: experimentally add fallback-to-outer (eat both)
My reasoning: the ruleset implemented by the same feature gate in Edition 2024 always tries to eat the inherited reference first. For consistency, it makes sense to me to say across all editions that users should consider the inherited reference's mutability when wondering if a `&mut` pattern will type.
This commit is contained in:
parent
799e0f7690
commit
20149629ba
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
|
||||
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 mut x] = &mut [&0];
|
||||
| ^^^^^^^^^^
|
||||
help: consider removing `&mut` from the pattern
|
||||
|
|
||||
LL - let [&mut 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:123:15
|
||||
|
|
||||
LL | let [&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 type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL - let [&mut &x] = &mut [&0];
|
||||
LL + let [&mut x] = &mut [&0];
|
||||
|
|
||||
= note: expected reference `&{integer}`
|
||||
found mutable reference `&mut _`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/well-typed-edition-2024.rs:129:10
|
||||
--> $DIR/well-typed-edition-2024.rs:129:15
|
||||
|
|
||||
LL | let [&mut &ref 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 type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
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 type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
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: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];
|
||||
| ^^^^^^^^^^^^^^ --------- 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];
|
||||
|
|
||||
| ^^^^^^^^^ 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`.
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user