1
Fork 0

"structural2021" ruleset: add fallback-to-outer (eat both) deref rule

This commit is contained in:
dianne 2025-01-26 00:27:37 -08:00
parent 8dc64a405d
commit 443c51d5d6
5 changed files with 156 additions and 184 deletions

View file

@ -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,

View file

@ -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`.

View file

@ -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;
}

View file

@ -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`.

View file

@ -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: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
|
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:114: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:120: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:126: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:132: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: aborting due to 11 previous errors
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];
| ^^^^^^^^^ cannot borrow as mutable
For more information about this error, try `rustc --explain E0308`.
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0308, E0596.
For more information about an error, try `rustc --explain E0308`.