From 372847dd4447bcb5a8c3595f70fd88002a580cbd Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 26 Jun 2024 17:01:04 -0400 Subject: [PATCH 1/3] Implement TC's match ergonomics 2024 proposal Under gate `ref_pat_eat_one_layer_2024_structural`. Enabling `ref_pat_eat_one_layer_2024` at the same time allows the union of what the individual gates allow. --- compiler/rustc_ast/src/ast.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_hir_typeck/src/pat.rs | 84 ++++++--- compiler/rustc_span/src/symbol.rs | 1 + ...feature-gate-ref_pat_eat_one_layer_2024.rs | 1 + ...ure-gate-ref_pat_eat_one_layer_2024.stderr | 20 +-- .../ref_pat_eat_one_layer_2024.rs | 12 +- ...ef_pat_eat_one_layer_2024_fail.both.stderr | 156 ++++++++++++++++ ...at_eat_one_layer_2024_fail.classic.stderr} | 56 +++--- .../ref_pat_eat_one_layer_2024_fail.rs | 24 ++- ..._eat_one_layer_2024_fail.structural.stderr | 167 ++++++++++++++++++ 11 files changed, 451 insertions(+), 73 deletions(-) create mode 100644 tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr rename tests/ui/match/ref_pat_eat_one_layer_2024/{ref_pat_eat_one_layer_2024_fail.stderr => ref_pat_eat_one_layer_2024_fail.classic.stderr} (76%) create mode 100644 tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4a3ce0e0c3066..9fcc0b25a2634 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -711,6 +711,7 @@ pub enum ByRef { } impl ByRef { + #[must_use] pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self { if let ByRef::Yes(old_mutbl) = &mut self { *old_mutbl = cmp::min(*old_mutbl, mutbl); diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index f4e20328814d7..f100d3e4ca84e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -573,6 +573,8 @@ declare_features! ( (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, "1.79.0", Some(123076)), + /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant + (incomplete, ref_pat_eat_one_layer_2024_structural, "1.79.0", Some(123076)), /// Allows using the `#[register_tool]` attribute. (unstable, register_tool, "1.41.0", Some(66079)), /// Allows the `#[repr(i128)]` attribute for enums. diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index aaf3d3ec34d01..8ce99e204e19f 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -328,8 +328,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { adjust_mode: AdjustMode, max_ref_mutbl: MutblCap, ) -> (Ty<'tcx>, ByRef, MutblCap) { - if let ByRef::Yes(Mutability::Mut) = def_br { - debug_assert!(max_ref_mutbl == MutblCap::Mut); + #[cfg(debug_assertions)] + if def_br == ByRef::Yes(Mutability::Mut) && max_ref_mutbl != MutblCap::Mut { + span_bug!(pat.span, "Pattern mutability cap violated!"); } match adjust_mode { AdjustMode::Pass => (expected, def_br, max_ref_mutbl), @@ -437,7 +438,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); } - if self.tcx.features().ref_pat_eat_one_layer_2024 { + let features = self.tcx.features(); + if features.ref_pat_eat_one_layer_2024 || features.ref_pat_eat_one_layer_2024_structural { def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl()); if def_br == ByRef::Yes(Mutability::Not) { max_ref_mutbl = MutblCap::Not; @@ -669,7 +671,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Determine the binding mode... let bm = match user_bind_annot { BindingMode(ByRef::No, Mutability::Mut) if matches!(def_br, ByRef::Yes(_)) => { - if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 { + if pat.span.at_least_rust_2024() + && (self.tcx.features().ref_pat_eat_one_layer_2024 + || self.tcx.features().ref_pat_eat_one_layer_2024_structural) + { if !self.tcx.features().mut_ref { feature_err( &self.tcx.sess, @@ -2122,7 +2127,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut expected: Ty<'tcx>, mut pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx> { - let no_ref_mut_behind_and = self.tcx.features().ref_pat_eat_one_layer_2024; + let tcx = self.tcx; + let features = tcx.features(); + let ref_pat_eat_one_layer_2024 = features.ref_pat_eat_one_layer_2024; + let ref_pat_eat_one_layer_2024_structural = features.ref_pat_eat_one_layer_2024_structural; + + let no_ref_mut_behind_and = + ref_pat_eat_one_layer_2024 || ref_pat_eat_one_layer_2024_structural; let new_match_ergonomics = pat.span.at_least_rust_2024() && no_ref_mut_behind_and; let pat_prefix_span = @@ -2137,32 +2148,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_info.max_ref_mutbl = MutblCap::Mut; } + expected = self.try_structurally_resolve_type(pat.span, expected); if new_match_ergonomics { if let ByRef::Yes(inh_mut) = pat_info.binding_mode { - // ref pattern consumes inherited reference - - if pat_mutbl > inh_mut { - // Tried to match inherited `ref` with `&mut`, which is an error - let err_msg = "cannot match inherited `&` with `&mut` pattern"; - let err = if let Some(span) = pat_prefix_span { - let mut err = self.dcx().struct_span_err(span, err_msg); - err.span_suggestion_verbose( - span, - "replace this `&mut` pattern with `&`", - "&", - Applicability::MachineApplicable, - ); - err + if !ref_pat_eat_one_layer_2024 && let ty::Ref(_, _, r_mutbl) = *expected.kind() { + // Don't attempt to consume inherited reference + pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(r_mutbl); + } else { + // ref pattern attempts to consume inherited reference + if pat_mutbl > inh_mut { + // Tried to match inherited `ref` with `&mut` + if !ref_pat_eat_one_layer_2024_structural { + let err_msg = "mismatched types"; + let err = if let Some(span) = pat_prefix_span { + let mut err = self.dcx().struct_span_err(span, err_msg); + err.code(E0308); + err.note("cannot match inherited `&` with `&mut` pattern"); + err.span_suggestion_verbose( + span, + "replace this `&mut` pattern with `&`", + "&", + Applicability::MachineApplicable, + ); + err + } else { + self.dcx().struct_span_err(pat.span, err_msg) + }; + err.emit(); + + pat_info.binding_mode = ByRef::No; + self.typeck_results + .borrow_mut() + .skipped_ref_pats_mut() + .insert(pat.hir_id); + self.check_pat(inner, expected, pat_info); + return expected; + } } else { - self.dcx().struct_span_err(pat.span, err_msg) - }; - err.emit(); + pat_info.binding_mode = ByRef::No; + self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); + self.check_pat(inner, expected, pat_info); + return expected; + } } - - pat_info.binding_mode = ByRef::No; - self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); - self.check_pat(inner, expected, pat_info); - return expected; } } else { // Reset binding mode on old editions @@ -2177,8 +2205,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let tcx = self.tcx; - expected = self.try_structurally_resolve_type(pat.span, expected); let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) { Ok(()) => { // `demand::subtype` would be good enough, but using `eqtype` turns diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6d4a8c29bc902..7cd5e4f7ce4c1 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1502,6 +1502,7 @@ symbols! { recursion_limit, reexport_test_harness_main, ref_pat_eat_one_layer_2024, + ref_pat_eat_one_layer_2024_structural, ref_pat_everywhere, ref_unwind_safe_trait, reference, diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs index 83f1ee6a77e89..7cbe8e0943ae4 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs @@ -1,5 +1,6 @@ //@ edition: 2024 //@ compile-flags: -Zunstable-options +// gate-test-ref_pat_eat_one_layer_2024_structural pub fn main() { if let Some(Some(&x)) = &Some(&Some(0)) { diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr index 132fe421a18d8..b3ea60252ac47 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:5:22 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:6:22 | LL | if let Some(Some(&x)) = &Some(&Some(0)) { | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` @@ -14,7 +14,7 @@ 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 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:11:23 | LL | let _: &u32 = x; | ---- ^ expected `&u32`, found integer @@ -27,7 +27,7 @@ LL | let _: &u32 = &x; | + error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:13:23 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:14:23 | LL | if let Some(Some(&&x)) = &Some(Some(&0)) { | ^^ --------------- this expression has type `&Option>` @@ -43,7 +43,7 @@ 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 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:18:17 | LL | if let Some(&Some(x)) = &Some(Some(0)) { | ^^^^^^^^ -------------- this expression has type `&Option>` @@ -54,7 +54,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { found reference `&_` error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:21:22 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:22:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>` @@ -64,7 +64,7 @@ LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { = 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 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:22:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ @@ -74,7 +74,7 @@ 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 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:26:22 | LL | if let Some(Some(&x)) = &Some(&Some(0)) { | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` @@ -89,7 +89,7 @@ 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 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:30:27 | LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { | ^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` @@ -104,7 +104,7 @@ 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 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:34:23 | LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) { | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` @@ -114,7 +114,7 @@ LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) { = 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 + --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:34:23 | LL | if let Some(&Some(&mut x)) = &mut Some(&Some(0)) { | ^^^^^^ diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs index 829b7f86e2621..0130189b874c6 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs @@ -1,8 +1,10 @@ //@ run-pass //@ edition: 2024 //@ compile-flags: -Zunstable-options +//@ revisions: classic structural both #![allow(incomplete_features)] -#![feature(ref_pat_eat_one_layer_2024)] +#![cfg_attr(any(classic, both), feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(any(structural, both), feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(Some(&x)) = &Some(&Some(0)) { @@ -53,4 +55,12 @@ pub fn main() { if let Some(&Some(x)) = &mut Some(Some(0)) { let _: u32 = x; } + #[cfg(any(classic, both))] + if let Some(&mut x) = &mut Some(&0) { + let _: &u32 = x; + } + #[cfg(any(structural, both))] + if let Some(&mut x) = &Some(&mut 0) { + let _: &u32 = x; + } } diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr new file mode 100644 index 0000000000000..f8931403774a3 --- /dev/null +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr @@ -0,0 +1,156 @@ +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:9: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:12:23 + | +LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { + | ^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:16:27 + | +LL | let _: &mut u32 = x; + | -------- ^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut u32` + found reference `&{integer}` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:19:23 + | +LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { + | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:22:29 + | +LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { + | ^^^^^^ ------------------------- this expression has type `&Option>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:25:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:28:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:9 + | +LL | let &mut _ = &&0; + | ^^^^^^ --- this expression has type `&&{integer}` + | | + | types differ in mutability + | + = note: expected reference `&&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:35:9 + | +LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; + | ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:46:9 + | +LL | let &mut _ = &&mut 0; + | ^^^^^^ ------- this expression has type `&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:49:9 + | +LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; + | ^^^^^^ --------------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:52:14 + | +LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; + | ^^^^^^^^^^^^^^^^ -------------------------- this expression has type `&mut &&&&mut &&&mut &mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&mut &&&mut &mut {integer}` + found mutable reference `&mut _` + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:61:13 + | +LL | let Foo(mut a) = &Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = 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/ref_pat_eat_one_layer_2024_fail.rs:65:13 + | +LL | let Foo(mut a) = &mut Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr similarity index 76% rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr rename to tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr index 26317e43d023e..0010a612c30f1 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr @@ -1,27 +1,29 @@ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:7:17 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:9:17 | LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:10:23 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:12:23 | LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:14:27 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:16:27 | LL | let _: &mut u32 = x; | -------- ^ types differ in mutability @@ -31,52 +33,56 @@ LL | let _: &mut u32 = x; = note: expected mutable reference `&mut u32` found reference `&{integer}` -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:17:23 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:19:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:20:29 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:22:29 | LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:23:17 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:25:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:28:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:30:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:9 | LL | let &mut _ = &&0; | ^^^^^^ --- this expression has type `&&{integer}` @@ -87,7 +93,7 @@ LL | let &mut _ = &&0; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:33:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:35:9 | LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; | ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` @@ -97,30 +103,32 @@ LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` found mutable reference `&mut _` -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:36:17 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:38:17 | LL | if let Some(&mut Some(&_)) = &Some(&mut Some(0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { | ~ -error: cannot match inherited `&` with `&mut` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:40:22 +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:42:22 | LL | if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { | ^^^^^ | + = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | LL | if let Some(Some(&x)) = &Some(Some(&mut 0)) { | ~ error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:44:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:46:9 | LL | let &mut _ = &&mut 0; | ^^^^^^ ------- this expression has type `&&mut {integer}` @@ -131,7 +139,7 @@ LL | let &mut _ = &&mut 0; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:47:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:49:9 | LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; | ^^^^^^ --------------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` @@ -142,7 +150,7 @@ LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:50:14 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:52:14 | LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; | ^^^^^^^^^^^^^^^^ -------------------------- this expression has type `&mut &&&&mut &&&mut &mut {integer}` @@ -153,7 +161,7 @@ LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; found mutable reference `&mut _` error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:55:13 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:61:13 | LL | let Foo(mut a) = &Foo(0); | ^^^^ @@ -163,7 +171,7 @@ LL | let Foo(mut a) = &Foo(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/ref_pat_eat_one_layer_2024_fail.rs:59:13 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:65:13 | LL | let Foo(mut a) = &mut Foo(0); | ^^^^ diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs index 40e8293e24111..4a40060b2ea40 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs @@ -1,30 +1,32 @@ //@ edition: 2024 //@ compile-flags: -Zunstable-options +//@ revisions: classic structural both #![allow(incomplete_features)] -#![feature(ref_pat_eat_one_layer_2024)] +#![cfg_attr(any(classic, both), feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(any(structural, both), feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(&mut Some(&_)) = &Some(&Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&Some(x)) = &mut Some(&Some(0)) { let _: &mut u32 = x; //~^ ERROR: mismatched types } if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&mut Some(x)) = &Some(Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } if let Some(&mut Some(x)) = &Some(Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //~^ ERROR: mismatched types } let &mut _ = &&0; @@ -34,11 +36,11 @@ pub fn main() { //~^ ERROR: mismatched types if let Some(&mut Some(&_)) = &Some(&mut Some(0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //[classic]~^ ERROR: mismatched types } if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { - //~^ ERROR: cannot match inherited `&` with `&mut` pattern + //[classic]~^ ERROR: mismatched types } let &mut _ = &&mut 0; @@ -50,6 +52,10 @@ pub fn main() { let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; //~^ ERROR: mismatched types + if let Some(&mut _) = &mut Some(&0) { + //[structural]~^ ERROR + } + struct Foo(u8); let Foo(mut a) = &Foo(0); diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr new file mode 100644 index 0000000000000..379bb6f4eaab3 --- /dev/null +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr @@ -0,0 +1,167 @@ +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:9: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:12:23 + | +LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { + | ^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:16:27 + | +LL | let _: &mut u32 = x; + | -------- ^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut u32` + found reference `&{integer}` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:19:23 + | +LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { + | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:22:29 + | +LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { + | ^^^^^^ ------------------------- this expression has type `&Option>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:25:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:28:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:9 + | +LL | let &mut _ = &&0; + | ^^^^^^ --- this expression has type `&&{integer}` + | | + | types differ in mutability + | + = note: expected reference `&&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:35:9 + | +LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; + | ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:46:9 + | +LL | let &mut _ = &&mut 0; + | ^^^^^^ ------- this expression has type `&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:49:9 + | +LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; + | ^^^^^^ --------------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:52:14 + | +LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; + | ^^^^^^^^^^^^^^^^ -------------------------- this expression has type `&mut &&&&mut &&&mut &mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&mut &&&mut &mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:55:17 + | +LL | if let Some(&mut _) = &mut Some(&0) { + | ^^^^^^ ------------- this expression has type `&mut Option<&{integer}>` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:61:13 + | +LL | let Foo(mut a) = &Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = 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/ref_pat_eat_one_layer_2024_fail.rs:65:13 + | +LL | let Foo(mut a) = &mut Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. From 35f6b7b97a7dd5fa21834a35faaa7470a071424a Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 26 Jun 2024 17:29:16 -0400 Subject: [PATCH 2/3] Fix tidy --- src/tools/tidy/src/features.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 3e84bf3c34be5..e8dff2dc26163 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -112,7 +112,7 @@ pub fn check( let file = entry.path(); let filename = file.file_name().unwrap().to_string_lossy(); let filen_underscore = filename.replace('-', "_").replace(".rs", ""); - let filename_is_gate_test = test_filen_gate(&filen_underscore, &mut features); + let filename_gate = test_filen_gate(&filen_underscore, &mut features); for (i, line) in contents.lines().enumerate() { let mut err = |msg: &str| { @@ -128,7 +128,7 @@ pub fn check( }; match features.get_mut(feature_name) { Some(f) => { - if filename_is_gate_test { + if filename_gate == Some(feature_name) { err(&format!( "The file is already marked as gate test \ through its name, no need for a \ @@ -259,18 +259,18 @@ fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> { r.captures(line).and_then(|c| c.get(1)).map(|m| m.as_str()) } -fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool { +fn test_filen_gate<'f>(filen_underscore: &'f str, features: &mut Features) -> Option<&'f str> { let prefix = "feature_gate_"; - if filen_underscore.starts_with(prefix) { + if let Some(suffix) = filen_underscore.strip_prefix(prefix) { for (n, f) in features.iter_mut() { // Equivalent to filen_underscore == format!("feature_gate_{n}") - if &filen_underscore[prefix.len()..] == n { + if suffix == n { f.has_gate_test = true; - return true; + return Some(suffix); } } } - false + None } pub fn collect_lang_features(base_compiler_path: &Path, bad: &mut bool) -> Features { From e09815f0efdf6a91f96974284b9e5129029da45f Mon Sep 17 00:00:00 2001 From: Guillaume Boisseau Date: Sun, 30 Jun 2024 14:26:28 +0200 Subject: [PATCH 3/3] New features gates mustn't specify a version by hand --- compiler/rustc_feature/src/unstable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index f100d3e4ca84e..8c30006e292b9 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -574,7 +574,7 @@ declare_features! ( /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant - (incomplete, ref_pat_eat_one_layer_2024_structural, "1.79.0", Some(123076)), + (incomplete, ref_pat_eat_one_layer_2024_structural, "CURRENT_RUSTC_VERSION", Some(123076)), /// Allows using the `#[register_tool]` attribute. (unstable, register_tool, "1.41.0", Some(66079)), /// Allows the `#[repr(i128)]` attribute for enums.