Match ergonomics 2024: Implement eat-one-layer
This commit is contained in:
parent
63f70b3d10
commit
93544d5db3
10 changed files with 471 additions and 50 deletions
|
@ -571,6 +571,8 @@ declare_features! (
|
|||
(unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
|
||||
/// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
|
||||
(unstable, raw_ref_op, "1.41.0", Some(64490)),
|
||||
/// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
|
||||
(incomplete, ref_pat_eat_one_layer_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
|
||||
/// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references.
|
||||
(incomplete, ref_pat_everywhere, "CURRENT_RUSTC_VERSION", Some(123076)),
|
||||
/// Allows using the `#[register_tool]` attribute.
|
||||
|
|
|
@ -294,7 +294,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
AdjustMode::Pass => (expected, def_bm, false),
|
||||
AdjustMode::Reset => (expected, INITIAL_BM, false),
|
||||
AdjustMode::ResetAndConsumeRef(mutbl) => {
|
||||
(expected, INITIAL_BM, def_bm.0 == ByRef::Yes(mutbl))
|
||||
let mutbls_match = def_bm.0 == ByRef::Yes(mutbl);
|
||||
if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
|
||||
if mutbls_match {
|
||||
(expected, INITIAL_BM, true)
|
||||
} else {
|
||||
(expected, def_bm, false)
|
||||
}
|
||||
} else {
|
||||
(expected, INITIAL_BM, mutbls_match)
|
||||
}
|
||||
}
|
||||
AdjustMode::Peel => {
|
||||
let peeled = self.peel_off_references(pat, expected, def_bm);
|
||||
|
@ -2056,6 +2065,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pat_info: PatInfo<'tcx, '_>,
|
||||
consumed_inherited_ref: bool,
|
||||
) -> Ty<'tcx> {
|
||||
if consumed_inherited_ref
|
||||
&& pat.span.at_least_rust_2024()
|
||||
&& self.tcx.features().ref_pat_eat_one_layer_2024
|
||||
{
|
||||
self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
|
||||
self.check_pat(inner, expected, pat_info);
|
||||
expected
|
||||
} else {
|
||||
let tcx = self.tcx;
|
||||
let expected = self.shallow_resolve(expected);
|
||||
let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
|
||||
|
@ -2112,6 +2129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.check_pat(inner, inner_ty, pat_info);
|
||||
ref_ty
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a reference type with a fresh region variable.
|
||||
fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
|
|
|
@ -1460,6 +1460,7 @@ symbols! {
|
|||
receiver,
|
||||
recursion_limit,
|
||||
reexport_test_harness_main,
|
||||
ref_pat_eat_one_layer_2024,
|
||||
ref_pat_everywhere,
|
||||
ref_unwind_safe_trait,
|
||||
reference,
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
//@ edition: 2024
|
||||
//@ compile-flags: -Zunstable-options
|
||||
|
||||
pub fn main() {
|
||||
if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&x)) = &Some(Some(&0)) {
|
||||
let _: &u32 = x;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
if let Some(Some(&&x)) = &Some(Some(&0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:5:22
|
||||
|
|
||||
LL | if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
| ^^ --------------- this expression has type `&Option<&Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL | if let Some(Some(x)) = &Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:10:23
|
||||
|
|
||||
LL | let _: &u32 = x;
|
||||
| ---- ^ expected `&u32`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | let _: &u32 = &x;
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:13:23
|
||||
|
|
||||
LL | if let Some(Some(&&x)) = &Some(Some(&0)) {
|
||||
| ^^ --------------- this expression has type `&Option<Option<&{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL - if let Some(Some(&&x)) = &Some(Some(&0)) {
|
||||
LL + if let Some(Some(&x)) = &Some(Some(&0)) {
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:17:17
|
||||
|
|
||||
LL | if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
| ^^^^^^^^ -------------- this expression has type `&Option<Option<{integer}>>`
|
||||
| |
|
||||
| expected `Option<{integer}>`, found `&_`
|
||||
|
|
||||
= note: expected enum `Option<{integer}>`
|
||||
found reference `&_`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:21:22
|
||||
|
|
||||
LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
| ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&mut _`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found mutable reference `&mut _`
|
||||
note: to declare a mutable binding use: `mut x`
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:21:22
|
||||
|
|
||||
LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
| ^^^^^^
|
||||
help: consider removing `&mut` from the pattern
|
||||
|
|
||||
LL | if let Some(Some(x)) = &mut Some(&mut Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:25:22
|
||||
|
|
||||
LL | if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
| ^^ --------------- this expression has type `&Option<&Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL | if let Some(Some(x)) = &Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:29:27
|
||||
|
|
||||
LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
|
||||
| ^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL | if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:33:23
|
||||
|
|
||||
LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
|
||||
| ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&mut _`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found mutable reference `&mut _`
|
||||
note: to declare a mutable binding use: `mut x`
|
||||
--> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:33:23
|
||||
|
|
||||
LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
|
||||
| ^^^^^^
|
||||
help: consider removing `&mut` from the pattern
|
||||
|
|
||||
LL | if let Some(&Some(x)) = &mut Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -0,0 +1,37 @@
|
|||
//@ edition: 2021
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(ref_pat_eat_one_layer_2024)]
|
||||
pub fn main() {
|
||||
if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&x)) = &Some(Some(&0)) {
|
||||
let _: &u32 = x;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
if let Some(Some(&&x)) = &Some(Some(&0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
let _: u32 = x;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:5:22
|
||||
|
|
||||
LL | if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
| ^^ --------------- this expression has type `&Option<&Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL | if let Some(Some(x)) = &Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:10:23
|
||||
|
|
||||
LL | let _: &u32 = x;
|
||||
| ---- ^ expected `&u32`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | let _: &u32 = &x;
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:13:23
|
||||
|
|
||||
LL | if let Some(Some(&&x)) = &Some(Some(&0)) {
|
||||
| ^^ --------------- this expression has type `&Option<Option<&{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL - if let Some(Some(&&x)) = &Some(Some(&0)) {
|
||||
LL + if let Some(Some(&x)) = &Some(Some(&0)) {
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:17:17
|
||||
|
|
||||
LL | if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
| ^^^^^^^^ -------------- this expression has type `&Option<Option<{integer}>>`
|
||||
| |
|
||||
| expected `Option<{integer}>`, found `&_`
|
||||
|
|
||||
= note: expected enum `Option<{integer}>`
|
||||
found reference `&_`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:21:22
|
||||
|
|
||||
LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
| ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&mut _`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found mutable reference `&mut _`
|
||||
note: to declare a mutable binding use: `mut x`
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:21:22
|
||||
|
|
||||
LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
| ^^^^^^
|
||||
help: consider removing `&mut` from the pattern
|
||||
|
|
||||
LL | if let Some(Some(x)) = &mut Some(&mut Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:25:22
|
||||
|
|
||||
LL | if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
| ^^ --------------- this expression has type `&Option<&Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL | if let Some(Some(x)) = &Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:29:27
|
||||
|
|
||||
LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
|
||||
| ^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL | if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
|
||||
| ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:33:23
|
||||
|
|
||||
LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
|
||||
| ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&mut _`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found mutable reference `&mut _`
|
||||
note: to declare a mutable binding use: `mut x`
|
||||
--> $DIR/ref_pat_eat_one_layer_2021.rs:33:23
|
||||
|
|
||||
LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
|
||||
| ^^^^^^
|
||||
help: consider removing `&mut` from the pattern
|
||||
|
|
||||
LL | if let Some(&Some(x)) = &mut Some(&Some(0)) {
|
||||
| ~
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -0,0 +1,32 @@
|
|||
//@ run-pass
|
||||
//@ edition: 2024
|
||||
//@ compile-flags: -Zunstable-options
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(ref_pat_eat_one_layer_2024)]
|
||||
|
||||
pub fn main() {
|
||||
if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&x)) = &Some(Some(&0)) {
|
||||
let _: &u32 = x;
|
||||
}
|
||||
if let Some(Some(&&x)) = &Some(Some(&0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&Some(x)) = &Some(Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(Some(&x)) = &Some(&Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
if let Some(&Some(&mut x)) = &mut Some(& Some(0)) {
|
||||
let _: u32 = x;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
//@ edition: 2024
|
||||
//@ compile-flags: -Zunstable-options
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(ref_pat_eat_one_layer_2024)]
|
||||
|
||||
pub fn main() {
|
||||
if let Some(&mut Some(&_)) = &Some(&Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
if let Some(&Some(&_)) = &Some(&mut Some(0)) {
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:7: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/ref_pat_eat_one_layer_2024_fail.rs:10:23
|
||||
|
|
||||
LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) {
|
||||
| ^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>`
|
||||
| |
|
||||
| expected integer, found `&_`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found reference `&_`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue