mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
"structural" ruleset: match against the inherited ref when a reference pattern doesn't match the mutability of an inner reference
This is the `Deref(EatInner, FallbackToOuter)` rule in Typing Rust Patterns.
This commit is contained in:
parent
f8315ae3b5
commit
586ff158a2
@ -2327,8 +2327,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return expected;
|
||||
}
|
||||
InheritedRefMatchRule::EatInner => {
|
||||
if let ty::Ref(_, _, r_mutbl) = *expected.kind() {
|
||||
if let ty::Ref(_, _, r_mutbl) = *expected.kind()
|
||||
&& pat_mutbl <= r_mutbl
|
||||
{
|
||||
// Match against the reference type; don't consume the inherited ref.
|
||||
// NB: The check for compatible pattern and ref type mutability assumes that
|
||||
// `&` patterns can match against mutable references (RFC 3627, Rule 5). If
|
||||
// we implement a pattern typing ruleset with Rule 4 (including the fallback
|
||||
// to matching the inherited ref when the inner ref can't match) but not
|
||||
// Rule 5, we'll need to check that here.
|
||||
debug_assert!(ref_pat_matches_mut_ref);
|
||||
// NB: For RFC 3627's Rule 3, we limit the default binding mode's ref
|
||||
// mutability to `pat_info.max_ref_mutbl`. If we implement a pattern typing
|
||||
// ruleset with Rule 4 but not Rule 3, we'll need to check that here.
|
||||
@ -2336,7 +2344,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let mutbl_cap = cmp::min(r_mutbl, pat_info.max_ref_mutbl.as_mutbl());
|
||||
pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(mutbl_cap);
|
||||
} else {
|
||||
// The expected type isn't a reference, so match against the inherited ref.
|
||||
// The reference pattern can't match against the expected type, so try
|
||||
// matching against the inherited ref instead.
|
||||
if pat_mutbl > inh_mut {
|
||||
// We can't match an inherited shared reference with `&mut`.
|
||||
// NB: This assumes that `&` patterns can match against mutable
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:15:17
|
||||
--> $DIR/pattern-errors.rs:10:17
|
||||
|
|
||||
LL | if let Some(&mut x) = &Some(&mut 0) {
|
||||
| ^^^^^
|
||||
@ -11,7 +11,7 @@ LL | if let Some(&x) = &Some(&mut 0) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:19:17
|
||||
--> $DIR/pattern-errors.rs:14:17
|
||||
|
|
||||
LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
|
||||
| ^^^^^
|
||||
@ -23,7 +23,7 @@ LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:23:22
|
||||
--> $DIR/pattern-errors.rs:18:22
|
||||
|
|
||||
LL | if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
|
||||
| ^^^^^
|
||||
@ -35,7 +35,7 @@ LL | if let Some(Some(&x)) = &Some(Some(&mut 0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:28:17
|
||||
--> $DIR/pattern-errors.rs:23:17
|
||||
|
|
||||
LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) {
|
||||
| ^^^^^
|
||||
@ -47,7 +47,7 @@ LL | if let Some(&Some(&_)) = &Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:34:23
|
||||
--> $DIR/pattern-errors.rs:29:23
|
||||
|
|
||||
LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
|
||||
| ^^^^^
|
||||
@ -59,7 +59,7 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:40:17
|
||||
--> $DIR/pattern-errors.rs:35:17
|
||||
|
|
||||
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
|
||||
| ^^^^^
|
||||
@ -71,7 +71,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:43:17
|
||||
--> $DIR/pattern-errors.rs:38:17
|
||||
|
|
||||
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
|
||||
| ^^^^^
|
||||
@ -83,7 +83,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:123:10
|
||||
--> $DIR/pattern-errors.rs:118:10
|
||||
|
|
||||
LL | let [&mut x] = &[&mut 0];
|
||||
| ^^^^^
|
||||
@ -95,7 +95,7 @@ LL | let [&x] = &[&mut 0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:128:10
|
||||
--> $DIR/pattern-errors.rs:123:10
|
||||
|
|
||||
LL | let [&mut &x] = &[&mut 0];
|
||||
| ^^^^^
|
||||
@ -107,7 +107,7 @@ LL | let [&&x] = &[&mut 0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:133:10
|
||||
--> $DIR/pattern-errors.rs:128:10
|
||||
|
|
||||
LL | let [&mut &ref x] = &[&mut 0];
|
||||
| ^^^^^
|
||||
@ -119,7 +119,7 @@ LL | let [&&ref x] = &[&mut 0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:138:10
|
||||
--> $DIR/pattern-errors.rs:133:10
|
||||
|
|
||||
LL | let [&mut &(mut x)] = &[&mut 0];
|
||||
| ^^^^^
|
||||
|
@ -7,11 +7,6 @@
|
||||
#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
|
||||
|
||||
pub fn main() {
|
||||
if let Some(&mut x) = &mut Some(&0) {
|
||||
//[structural]~^ ERROR: mismatched types
|
||||
let _: &u32 = x;
|
||||
}
|
||||
|
||||
if let Some(&mut x) = &Some(&mut 0) {
|
||||
//[classic]~^ ERROR: mismatched types
|
||||
let _: &u32 = x;
|
||||
|
@ -1,36 +1,17 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:10:17
|
||||
--> $DIR/pattern-errors.rs:23:17
|
||||
|
|
||||
LL | if let Some(&mut x) = &mut Some(&0) {
|
||||
| ^^^^^^ ------------- this expression has type `&mut Option<&{integer}>`
|
||||
| |
|
||||
| types differ in mutability
|
||||
LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) {
|
||||
| ^^^^^
|
||||
|
|
||||
= note: expected reference `&{integer}`
|
||||
found mutable reference `&mut _`
|
||||
note: to declare a mutable binding use: `mut x`
|
||||
--> $DIR/pattern-errors.rs:10:17
|
||||
= note: cannot match inherited `&` with `&mut` pattern
|
||||
help: replace this `&mut` pattern with `&`
|
||||
|
|
||||
LL | if let Some(&mut x) = &mut Some(&0) {
|
||||
| ^^^^^^
|
||||
help: consider removing `&mut` from the pattern
|
||||
|
|
||||
LL | if let Some(x) = &mut Some(&0) {
|
||||
LL | if let Some(&Some(&_)) = &Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:28:17
|
||||
|
|
||||
LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) {
|
||||
| ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>`
|
||||
| |
|
||||
| types differ in mutability
|
||||
|
|
||||
= note: expected reference `&Option<{integer}>`
|
||||
found mutable reference `&mut _`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:31:23
|
||||
--> $DIR/pattern-errors.rs:26:23
|
||||
|
|
||||
LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
|
||||
| ^^^^^
|
||||
@ -42,7 +23,7 @@ LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:34:23
|
||||
--> $DIR/pattern-errors.rs:29:23
|
||||
|
|
||||
LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
|
||||
| ^^^^^
|
||||
@ -54,7 +35,7 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:37:29
|
||||
--> $DIR/pattern-errors.rs:32:29
|
||||
|
|
||||
LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
|
||||
| ^^^^^
|
||||
@ -66,7 +47,7 @@ LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:40:17
|
||||
--> $DIR/pattern-errors.rs:35:17
|
||||
|
|
||||
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
|
||||
| ^^^^^
|
||||
@ -78,7 +59,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:43:17
|
||||
--> $DIR/pattern-errors.rs:38:17
|
||||
|
|
||||
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
|
||||
| ^^^^^
|
||||
@ -90,7 +71,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:49:11
|
||||
--> $DIR/pattern-errors.rs:44:11
|
||||
|
|
||||
LL | let &[&mut x] = &&mut [0];
|
||||
| ^^^^^
|
||||
@ -102,7 +83,7 @@ LL | let &[&x] = &&mut [0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:54:11
|
||||
--> $DIR/pattern-errors.rs:49:11
|
||||
|
|
||||
LL | let &[&mut x] = &mut &mut [0];
|
||||
| ^^^^^
|
||||
@ -114,7 +95,7 @@ LL | let &[&x] = &mut &mut [0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:59:11
|
||||
--> $DIR/pattern-errors.rs:54:11
|
||||
|
|
||||
LL | let &[&mut ref x] = &&mut [0];
|
||||
| ^^^^^
|
||||
@ -126,7 +107,7 @@ LL | let &[&ref x] = &&mut [0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:64:11
|
||||
--> $DIR/pattern-errors.rs:59:11
|
||||
|
|
||||
LL | let &[&mut ref x] = &mut &mut [0];
|
||||
| ^^^^^
|
||||
@ -138,7 +119,7 @@ LL | let &[&ref x] = &mut &mut [0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:69:11
|
||||
--> $DIR/pattern-errors.rs:64:11
|
||||
|
|
||||
LL | let &[&mut mut x] = &&mut [0];
|
||||
| ^^^^^
|
||||
@ -150,7 +131,7 @@ LL | let &[&mut x] = &&mut [0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:74:11
|
||||
--> $DIR/pattern-errors.rs:69:11
|
||||
|
|
||||
LL | let &[&mut mut x] = &mut &mut [0];
|
||||
| ^^^^^
|
||||
@ -162,7 +143,7 @@ LL | let &[&mut x] = &mut &mut [0];
|
||||
| ~
|
||||
|
||||
error[E0658]: binding cannot be both mutable and by-reference
|
||||
--> $DIR/pattern-errors.rs:81:12
|
||||
--> $DIR/pattern-errors.rs:76:12
|
||||
|
|
||||
LL | let [&(mut x)] = &[&0];
|
||||
| ^^^^
|
||||
@ -172,7 +153,7 @@ LL | let [&(mut x)] = &[&0];
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: binding cannot be both mutable and by-reference
|
||||
--> $DIR/pattern-errors.rs:85:12
|
||||
--> $DIR/pattern-errors.rs:80:12
|
||||
|
|
||||
LL | let [&(mut x)] = &mut [&0];
|
||||
| ^^^^
|
||||
@ -182,7 +163,7 @@ LL | let [&(mut x)] = &mut [&0];
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:91:11
|
||||
--> $DIR/pattern-errors.rs:86:11
|
||||
|
|
||||
LL | let [&&mut x] = &[&mut 0];
|
||||
| ^^^^^
|
||||
@ -194,7 +175,7 @@ LL | let [&&x] = &[&mut 0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:96:11
|
||||
--> $DIR/pattern-errors.rs:91:11
|
||||
|
|
||||
LL | let [&&mut x] = &mut [&mut 0];
|
||||
| ^^^^^
|
||||
@ -206,7 +187,7 @@ LL | let [&&x] = &mut [&mut 0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:101:11
|
||||
--> $DIR/pattern-errors.rs:96:11
|
||||
|
|
||||
LL | let [&&mut ref x] = &[&mut 0];
|
||||
| ^^^^^
|
||||
@ -218,7 +199,7 @@ LL | let [&&ref x] = &[&mut 0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:106:11
|
||||
--> $DIR/pattern-errors.rs:101:11
|
||||
|
|
||||
LL | let [&&mut ref x] = &mut [&mut 0];
|
||||
| ^^^^^
|
||||
@ -230,7 +211,7 @@ LL | let [&&ref x] = &mut [&mut 0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:111:11
|
||||
--> $DIR/pattern-errors.rs:106:11
|
||||
|
|
||||
LL | let [&&mut mut x] = &[&mut 0];
|
||||
| ^^^^^
|
||||
@ -242,7 +223,7 @@ LL | let [&&mut x] = &[&mut 0];
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-errors.rs:116:11
|
||||
--> $DIR/pattern-errors.rs:111:11
|
||||
|
|
||||
LL | let [&&mut mut x] = &mut [&mut 0];
|
||||
| ^^^^^
|
||||
@ -253,7 +234,7 @@ help: replace this `&mut` pattern with `&`
|
||||
LL | let [&&mut x] = &mut [&mut 0];
|
||||
| ~
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
error: aborting due to 20 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0658.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -3,7 +3,7 @@
|
||||
//@ run-pass
|
||||
//! Test cases for well-typed patterns in edition 2024. These are in their own file to ensure we
|
||||
//! pass both HIR typeck and MIR borrowck, as we may skip the latter if grouped with failing tests.
|
||||
#![allow(incomplete_features)]
|
||||
#![allow(incomplete_features, unused_mut)]
|
||||
#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
|
||||
#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
|
||||
|
||||
@ -53,4 +53,27 @@ pub fn main() {
|
||||
if let Some(&Some(x)) = &mut Some(Some(0)) {
|
||||
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)`:
|
||||
let [&mut x] = &mut [&0];
|
||||
let _: &u32 = x;
|
||||
|
||||
let [&mut ref x] = &mut [&0];
|
||||
let _: &&u32 = x;
|
||||
|
||||
let [&mut ref mut x] = &mut [&0];
|
||||
let _: &mut &u32 = x;
|
||||
|
||||
let [&mut mut x] = &mut [&0];
|
||||
let _: &u32 = x;
|
||||
|
||||
let [&mut &x] = &mut [&0];
|
||||
let _: u32 = x;
|
||||
|
||||
let [&mut &ref x] = &mut [&0];
|
||||
let _: &u32 = x;
|
||||
|
||||
let [&mut &(mut x)] = &mut [&0];
|
||||
let _: u32 = x;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user