summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-05 09:10:17 +0000
committerbors <bors@rust-lang.org>2024-07-05 09:10:17 +0000
commit2ad66306738f8fb4b88f7ac19f3a80491ce28e29 (patch)
treeb180768064535efd413675774acd4ce9ee225bdb
parentd2e6cf7fa78500d6c264e35468278aeffd806258 (diff)
parente09815f0efdf6a91f96974284b9e5129029da45f (diff)
Auto merge of #127008 - Jules-Bertholet:tc-ergonomics, r=Nadrieril
Match ergonomics 2024: Implement TC's match ergonomics 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. `@traviscross` r? `@Nadrieril` cc https://github.com/rust-lang/rust/issues/123076 `@rustbot` label A-edition-2024 A-patterns
-rw-r--r--compiler/rustc_ast/src/ast.rs1
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs84
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--src/tools/tidy/src/features.rs14
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs1
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr20
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs12
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr156
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr (renamed from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr)56
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs24
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr167
12 files changed, 458 insertions, 80 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index dbbc4980050..f2cdedc0087 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -714,6 +714,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 ad6f7da8937..c05cac155b7 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -575,6 +575,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, "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.
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 478bbc0ed98..c8db4b97bae 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,
@@ -2123,7 +2128,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 =
@@ -2138,32 +2149,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
@@ -2178,8 +2206,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 7da9211bcbf..af56f4e5141 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1513,6 +1513,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/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 3e84bf3c34b..e8dff2dc261 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 {
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 83f1ee6a77e..7cbe8e0943a 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 132fe421a18..b3ea60252ac 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<Option<&{integer}>>`
@@ -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<Option<{integer}>>`
@@ -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 829b7f86e26..0130189b874 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 00000000000..f8931403774
--- /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<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:25:17
+ |
+LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
+ | ^^^^^^^^^^^^ -------------- this expression has type `&Option<Option<{integer}>>`
+ | |
+ | 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<Option<{integer}>>`
+ | |
+ | 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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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
index 26317e43d02..0010a612c30 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 40e8293e241..4a40060b2ea 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 00000000000..379bb6f4eaa
--- /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<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:25:17
+ |
+LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
+ | ^^^^^^^^^^^^ -------------- this expression has type `&Option<Option<{integer}>>`
+ | |
+ | 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<Option<{integer}>>`
+ | |
+ | 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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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`.