diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 8cc4c18c02abf..a30a797beffaa 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -718,7 +718,8 @@ impl Features {
/// Some features are not allowed to be used together at the same time, if
/// the two are present, produce an error.
-///
-/// Currently empty, but we will probably need this again in the future,
-/// so let's keep it in for now.
-pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[];
+pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[
+ // Experimental match ergonomics rulesets are incompatible with each other, to simplify the
+ // boolean logic required to tell which typing rules to use.
+ (sym::ref_pat_eat_one_layer_2024, sym::ref_pat_eat_one_layer_2024_structural),
+];
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 4870e6193c3f1..1913bc0e741cd 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -21,6 +21,7 @@ use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_session::parse::feature_err;
use rustc_span::edit_distance::find_best_match_for_name;
+use rustc_span::edition::Edition;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::Spanned;
use rustc_span::{BytePos, DUMMY_SP, Ident, Span, kw, sym};
@@ -168,15 +169,16 @@ enum AdjustMode {
Pass,
}
-/// `ref mut` patterns (explicit or match-ergonomics)
-/// are not allowed behind an `&` reference.
+/// `ref mut` bindings (explicit or match-ergonomics) are not allowed behind an `&` reference.
+/// Normally, the borrow checker enforces this, but for (currently experimental) match ergonomics,
+/// we track this when typing patterns for two purposes:
///
-/// This includes explicit `ref mut` behind `&` patterns
-/// that match against `&mut` references,
-/// where the code would have compiled
-/// had the pattern been written as `&mut`.
-/// However, the borrow checker will not catch
-/// this last case, so we need to throw an error ourselves.
+/// - For RFC 3627's Rule 3, when this would prevent us from binding with `ref mut`, we limit the
+/// default binding mode to be by shared `ref` when it would otherwise be `ref mut`.
+///
+/// - For RFC 3627's Rule 5, we allow `&` patterns to match against `&mut` references, treating them
+/// as if they were shared references. Since the scrutinee is mutable in this case, the borrow
+/// checker won't catch if we bind with `ref mut`, so we need to throw an error ourselves.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum MutblCap {
/// Mutability restricted to immutable.
@@ -212,7 +214,67 @@ impl MutblCap {
}
}
+/// Variations on RFC 3627's Rule 4: when do reference patterns match against inherited references?
+///
+/// "Inherited reference" designates the `&`/`&mut` types that arise from using match ergonomics, i.e.
+/// from matching a reference type with a non-reference pattern. E.g. when `Some(x)` matches on
+/// `&mut Option<&T>`, `x` gets type `&mut &T` and the outer `&mut` is considered "inherited".
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum InheritedRefMatchRule {
+ /// Reference patterns consume only the inherited reference if possible, regardless of whether
+ /// the underlying type being matched against is a reference type. If there is no inherited
+ /// reference, a reference will be consumed from the underlying type.
+ EatOuter,
+ /// Reference patterns consume only a reference from the underlying type if possible. If the
+ /// underlying type is not a reference type, the inherited reference will be consumed.
+ EatInner,
+ /// When the underlying type is a reference type, reference patterns consume both layers of
+ /// reference, i.e. they both reset the binding mode and consume the reference type. Reference
+ /// patterns are not permitted when there is no underlying reference type, i.e. they can't eat
+ /// only an inherited reference. This is the current stable Rust behavior.
+ EatBoth,
+}
+
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+ /// Experimental pattern feature: after matching against a shared reference, do we limit the
+ /// default binding mode in subpatterns to be `ref` when it would otherwise be `ref mut`?
+ /// This corresponds to Rule 3 of RFC 3627.
+ fn downgrade_mut_inside_shared(&self) -> bool {
+ // NB: RFC 3627 proposes stabilizing Rule 3 in all editions. If we adopt the same behavior
+ // across all editions, this may be removed.
+ self.tcx.features().ref_pat_eat_one_layer_2024()
+ || self.tcx.features().ref_pat_eat_one_layer_2024_structural()
+ }
+
+ /// Experimental pattern feature: when do reference patterns match against inherited references?
+ /// This corresponds to variations on Rule 4 of RFC 3627.
+ fn ref_pat_matches_inherited_ref(&self, edition: Edition) -> InheritedRefMatchRule {
+ // NB: The particular rule used here is likely to differ across editions, so calls to this
+ // may need to become edition checks after match ergonomics stabilize.
+ if edition.at_least_rust_2024() {
+ if self.tcx.features().ref_pat_eat_one_layer_2024() {
+ InheritedRefMatchRule::EatOuter
+ } else if self.tcx.features().ref_pat_eat_one_layer_2024_structural() {
+ InheritedRefMatchRule::EatInner
+ } else {
+ // Currently, matching against an inherited ref on edition 2024 is an error.
+ // Use `EatBoth` as a fallback to be similar to stable Rust.
+ InheritedRefMatchRule::EatBoth
+ }
+ } else {
+ InheritedRefMatchRule::EatBoth
+ }
+ }
+
+ /// Experimental pattern feature: do `&` patterns match against `&mut` references, treating them
+ /// as if they were shared references? This corresponds to Rule 5 of RFC 3627.
+ fn ref_pat_matches_mut_ref(&self) -> bool {
+ // NB: RFC 3627 proposes stabilizing Rule 5 in all editions. If we adopt the same behavior
+ // across all editions, this may be removed.
+ self.tcx.features().ref_pat_eat_one_layer_2024()
+ || self.tcx.features().ref_pat_eat_one_layer_2024_structural()
+ }
+
/// Type check the given top level pattern against the `expected` type.
///
/// If a `Some(span)` is provided and `origin_expr` holds,
@@ -473,13 +535,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
}
- let features = self.tcx.features();
- if features.ref_pat_eat_one_layer_2024() || features.ref_pat_eat_one_layer_2024_structural()
- {
+ if self.downgrade_mut_inside_shared() {
def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
- if def_br == ByRef::Yes(Mutability::Not) {
- max_ref_mutbl = MutblCap::Not;
- }
+ }
+ if def_br == ByRef::Yes(Mutability::Not) {
+ max_ref_mutbl = MutblCap::Not;
}
if !pat_adjustments.is_empty() {
@@ -707,6 +767,8 @@ 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(_)) => {
+ // Only mention the experimental `mut_ref` feature if if we're in edition 2024 and
+ // using other experimental matching features compatible with it.
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())
@@ -2204,55 +2266,70 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mut pat_info: PatInfo<'_, 'tcx>,
) -> Ty<'tcx> {
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 =
inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end));
- if no_ref_mut_behind_and {
- if pat_mutbl == Mutability::Not {
- // Prevent the inner pattern from binding with `ref mut`.
- pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span);
- }
- } else {
- pat_info.max_ref_mutbl = MutblCap::Mut;
+ let ref_pat_matches_mut_ref = self.ref_pat_matches_mut_ref();
+ if ref_pat_matches_mut_ref && pat_mutbl == Mutability::Not {
+ // If `&` patterns can match against mutable reference types (RFC 3627, Rule 5), we need
+ // to prevent subpatterns from binding with `ref mut`. Subpatterns of a shared reference
+ // pattern should have read-only access to the scrutinee, and the borrow checker won't
+ // catch it in this case.
+ pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span);
}
expected = self.try_structurally_resolve_type(pat.span, expected);
- if new_match_ergonomics {
- if let ByRef::Yes(inh_mut) = pat_info.binding_mode {
- 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 {
+ // Determine whether we're consuming an inherited reference and resetting the default
+ // binding mode, based on edition and enabled experimental features.
+ if let ByRef::Yes(inh_mut) = pat_info.binding_mode {
+ match self.ref_pat_matches_inherited_ref(pat.span.edition()) {
+ InheritedRefMatchRule::EatOuter => {
// 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();
+ // NB: This assumes that `&` patterns can match against mutable references
+ // (RFC 3627, Rule 5). If we implement a pattern typing ruleset with Rule 4E
+ // but not Rule 5, we'll need to check that here.
+ debug_assert!(ref_pat_matches_mut_ref);
+ 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;
+ }
+ InheritedRefMatchRule::EatInner => {
+ if let ty::Ref(_, _, r_mutbl) = *expected.kind() {
+ // Match against the reference type; don't consume the inherited ref.
+ pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(r_mutbl);
+ } else {
+ // The expected type isn't a reference, so match against the inherited ref.
+ if pat_mutbl > inh_mut {
+ // We can't match an inherited shared reference with `&mut`. This will
+ // be a type error later, since we're matching a reference pattern
+ // against a non-reference type.
+ // NB: This assumes that `&` patterns can match against mutable
+ // references (RFC 3627, Rule 5). If we implement a pattern typing
+ // ruleset with Rule 4 but not Rule 5, we'll need to check that here.
+ debug_assert!(ref_pat_matches_mut_ref);
+ } else {
pat_info.binding_mode = ByRef::No;
self.typeck_results
.borrow_mut()
@@ -2261,24 +2338,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_pat(inner, expected, pat_info);
return expected;
}
- } else {
- 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
- if pat_info.binding_mode != ByRef::No {
- pat_info.binding_mode = ByRef::No;
- self.add_rust_2024_migration_desugared_pat(
- pat_info.top_info.hir_id,
- pat.span,
- inner.span,
- "cannot implicitly match against multiple layers of reference",
- )
+ InheritedRefMatchRule::EatBoth => {
+ // Reset binding mode on old editions
+ pat_info.binding_mode = ByRef::No;
+ self.add_rust_2024_migration_desugared_pat(
+ pat_info.top_info.hir_id,
+ pat.span,
+ inner.span,
+ "cannot implicitly match against multiple layers of reference",
+ )
+ }
}
}
@@ -2293,10 +2364,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("check_pat_ref: expected={:?}", expected);
match *expected.kind() {
ty::Ref(_, r_ty, r_mutbl)
- if (no_ref_mut_behind_and && r_mutbl >= pat_mutbl)
+ if (ref_pat_matches_mut_ref && r_mutbl >= pat_mutbl)
|| r_mutbl == pat_mutbl =>
{
- if no_ref_mut_behind_and && r_mutbl == Mutability::Not {
+ if r_mutbl == Mutability::Not {
pat_info.max_ref_mutbl = MutblCap::Not;
}
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
deleted file mode 100644
index f8672d755b959..0000000000000
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.both.stderr
+++ /dev/null
@@ -1,169 +0,0 @@
-error[E0308]: mismatched types
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:8: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:11: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:15: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:18: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:21: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:24: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:27: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:31: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:34: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:45: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:48: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:51: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:60: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:64: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[E0277]: the trait bound `&_: main::Ref` is not satisfied
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:82:14
- |
-LL | let &_ = generic();
- | ^^^^^^^^^ the trait `main::Ref` is not implemented for `&_`
- |
- = help: the trait `main::Ref` is implemented for `&'static mut [(); 0]`
-note: required by a bound in `generic`
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:68:19
- |
-LL | fn generic() -> R {
- | ^^^ required by this bound in `generic`
-
-error: aborting due to 15 previous errors
-
-Some errors have detailed explanations: E0277, E0308, E0658.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr
deleted file mode 100644
index a37316b3097b0..0000000000000
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.classic.stderr
+++ /dev/null
@@ -1,199 +0,0 @@
-error[E0308]: mismatched types
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:8: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[E0308]: mismatched types
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:11: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:15: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:18: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[E0308]: mismatched types
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:21: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[E0308]: mismatched types
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:24: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:27: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:31: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:34: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:37: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[E0308]: mismatched types
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:41: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:45: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:48: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:51: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:60: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:64: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[E0277]: the trait bound `&_: main::Ref` is not satisfied
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:82:14
- |
-LL | let &_ = generic();
- | ^^^^^^^^^ the trait `main::Ref` is not implemented for `&_`
- |
- = help: the trait `main::Ref` is implemented for `&'static mut [(); 0]`
-note: required by a bound in `generic`
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:68:19
- |
-LL | fn generic() -> R {
- | ^^^ required by this bound in `generic`
-
-error: aborting due to 17 previous errors
-
-Some errors have detailed explanations: E0277, E0308, E0658.
-For more information about an error, try `rustc --explain E0277`.
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
deleted file mode 100644
index fd616807b285c..0000000000000
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-//@ edition: 2024
-//@ revisions: classic structural both
-#![allow(incomplete_features)]
-#![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: mismatched types
- }
- if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
- //~^ 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: mismatched types
- }
- if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
- //~^ ERROR: mismatched types
- }
- if let Some(&mut Some(x)) = &Some(Some(0)) {
- //~^ ERROR: mismatched types
- }
- if let Some(&mut Some(x)) = &Some(Some(0)) {
- //~^ ERROR: mismatched types
- }
-
- let &mut _ = &&0;
- //~^ ERROR: mismatched types
-
- let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
- //~^ ERROR: mismatched types
-
- if let Some(&mut Some(&_)) = &Some(&mut Some(0)) {
- //[classic]~^ ERROR: mismatched types
- }
-
- if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
- //[classic]~^ ERROR: mismatched types
- }
-
- let &mut _ = &&mut 0;
- //~^ ERROR: mismatched types
-
- let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
- //~^ ERROR: mismatched types
-
- 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);
- //~^ ERROR: binding cannot be both mutable and by-reference
- a = &42;
-
- let Foo(mut a) = &mut Foo(0);
- //~^ ERROR: binding cannot be both mutable and by-reference
- a = &mut 42;
-
- fn generic() -> R {
- R::meow()
- }
-
- trait Ref: Sized {
- fn meow() -> Self;
- }
-
- impl Ref for &'static mut [(); 0] {
- fn meow() -> Self {
- &mut []
- }
- }
-
- let &_ = generic(); //~ERROR: the trait bound `&_: main::Ref` is not satisfied [E0277]
-}
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
deleted file mode 100644
index 2f62e9974fa3f..0000000000000
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.structural.stderr
+++ /dev/null
@@ -1,180 +0,0 @@
-error[E0308]: mismatched types
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:8: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:11: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:15: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:18: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:21: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:24: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:27: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:31: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:34: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:45: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:48: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:51: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:54: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:60: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:64: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[E0277]: the trait bound `&_: main::Ref` is not satisfied
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:82:14
- |
-LL | let &_ = generic();
- | ^^^^^^^^^ the trait `main::Ref` is not implemented for `&_`
- |
- = help: the trait `main::Ref` is implemented for `&'static mut [(); 0]`
-note: required by a bound in `generic`
- --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:68:19
- |
-LL | fn generic() -> R {
- | ^^^ required by this bound in `generic`
-
-error: aborting due to 16 previous errors
-
-Some errors have detailed explanations: E0277, E0308, E0658.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/pattern/no_ref_mut_behind_and.rs b/tests/ui/pattern/no_ref_mut_behind_and.rs
deleted file mode 100644
index c18d64904d035..0000000000000
--- a/tests/ui/pattern/no_ref_mut_behind_and.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ edition: 2021
-//@ run-pass
-#![allow(incomplete_features)]
-#![feature(ref_pat_eat_one_layer_2024)]
-
-fn main() {
- let &[[x]] = &[&mut [42]];
- let _: &i32 = x;
-}
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr
similarity index 88%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr
index a8b813941109c..c62461140750b 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr
@@ -1,5 +1,5 @@
error[E0507]: cannot move out of a shared reference
- --> $DIR/ref_pat_eat_one_layer_2024_fail2.rs:6:29
+ --> $DIR/borrowck-errors.rs:9:29
|
LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) {
| - ^^^^^^^^^^^^^^^^^^^
@@ -14,7 +14,7 @@ LL + if let Some(Some(x)) = Some(&Some(&mut 0)) {
|
error[E0596]: cannot borrow data in a `&` reference as mutable
- --> $DIR/ref_pat_eat_one_layer_2024_fail2.rs:11:10
+ --> $DIR/borrowck-errors.rs:14:10
|
LL | let &ref mut x = &0;
| ^^^^^^^^^ cannot borrow as mutable
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
similarity index 54%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
index 79403b1936528..a01e9ca265760 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
@@ -1,6 +1,9 @@
//@ edition: 2024
+//@ revisions: classic structural
+//! Tests for pattern errors not handled by the pattern typing rules, but by borrowck.
#![allow(incomplete_features)]
-#![feature(ref_pat_eat_one_layer_2024)]
+#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
pub fn main() {
if let Some(&Some(x)) = Some(&Some(&mut 0)) {
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural.stderr
new file mode 100644
index 0000000000000..c62461140750b
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural.stderr
@@ -0,0 +1,25 @@
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/borrowck-errors.rs:9:29
+ |
+LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+ | - ^^^^^^^^^^^^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+LL + if let Some(Some(x)) = Some(&Some(&mut 0)) {
+ |
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+ --> $DIR/borrowck-errors.rs:14:10
+ |
+LL | let &ref mut x = &0;
+ | ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0507, E0596.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic.stderr
new file mode 100644
index 0000000000000..89a52ba7d1ddb
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic.stderr
@@ -0,0 +1,58 @@
+error[E0308]: mismatched types
+ --> $DIR/cannot-mutably-deref-shared-ref.rs:9: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/cannot-mutably-deref-shared-ref.rs:12: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/cannot-mutably-deref-shared-ref.rs:15: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/cannot-mutably-deref-shared-ref.rs:18: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/cannot-mutably-deref-shared-ref.rs:21: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: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs
new file mode 100644
index 0000000000000..e22bd1f8f6c99
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs
@@ -0,0 +1,23 @@
+//@ edition: 2024
+//@ revisions: classic structural
+//! Test that `&mut` patterns don't match shared reference types under new typing rules in Rust 2024
+#![allow(incomplete_features)]
+#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
+
+pub fn main() {
+ let &mut _ = &&0;
+ //~^ ERROR: mismatched types
+
+ let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
+ //~^ ERROR: mismatched types
+
+ let &mut _ = &&mut 0;
+ //~^ ERROR: mismatched types
+
+ let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
+ //~^ ERROR: mismatched types
+
+ let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0;
+ //~^ ERROR: mismatched types
+}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural.stderr
new file mode 100644
index 0000000000000..89a52ba7d1ddb
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural.stderr
@@ -0,0 +1,58 @@
+error[E0308]: mismatched types
+ --> $DIR/cannot-mutably-deref-shared-ref.rs:9: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/cannot-mutably-deref-shared-ref.rs:12: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/cannot-mutably-deref-shared-ref.rs:15: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/cannot-mutably-deref-shared-ref.rs:18: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/cannot-mutably-deref-shared-ref.rs:21: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: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/feature-gate-ref_pat_eat_one_layer_2024.rs
similarity index 100%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/feature-gate-ref_pat_eat_one_layer_2024.rs
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/feature-gate-ref_pat_eat_one_layer_2024.stderr
similarity index 100%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/feature-gate-ref_pat_eat_one_layer_2024.stderr
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic.stderr
new file mode 100644
index 0000000000000..43560a1803026
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic.stderr
@@ -0,0 +1,23 @@
+error[E0658]: binding cannot be both mutable and by-reference
+ --> $DIR/mut-ref-mut.rs:11: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/mut-ref-mut.rs:15: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 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs
new file mode 100644
index 0000000000000..786587984ba41
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs
@@ -0,0 +1,18 @@
+//@ edition: 2024
+//@ revisions: classic structural
+//! Test diagnostics for binding with `mut` when the default binding mode is by-ref.
+#![allow(incomplete_features)]
+#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
+
+pub fn main() {
+ struct Foo(u8);
+
+ let Foo(mut a) = &Foo(0);
+ //~^ ERROR: binding cannot be both mutable and by-reference
+ a = &42;
+
+ let Foo(mut a) = &mut Foo(0);
+ //~^ ERROR: binding cannot be both mutable and by-reference
+ a = &mut 42;
+}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural.stderr
new file mode 100644
index 0000000000000..43560a1803026
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural.stderr
@@ -0,0 +1,23 @@
+error[E0658]: binding cannot be both mutable and by-reference
+ --> $DIR/mut-ref-mut.rs:11: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/mut-ref-mut.rs:15: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 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr
new file mode 100644
index 0000000000000..2bc3ecb7636d0
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr
@@ -0,0 +1,111 @@
+error[E0308]: mismatched types
+ --> $DIR/pattern-errors.rs:15:17
+ |
+LL | if let Some(&mut x) = &Some(&mut 0) {
+ | ^^^^^
+ |
+ = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+ |
+LL | if let Some(&x) = &Some(&mut 0) {
+ | ~
+
+error[E0308]: mismatched types
+ --> $DIR/pattern-errors.rs:19:17
+ |
+LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+ | ^^^^^
+ |
+ = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+ |
+LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+ | ~
+
+error[E0308]: mismatched types
+ --> $DIR/pattern-errors.rs:23: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/pattern-errors.rs:28: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[E0308]: mismatched types
+ --> $DIR/pattern-errors.rs:31: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/pattern-errors.rs:34: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[E0308]: mismatched types
+ --> $DIR/pattern-errors.rs:37: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[E0308]: mismatched types
+ --> $DIR/pattern-errors.rs:40: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/pattern-errors.rs:43: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: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
new file mode 100644
index 0000000000000..3535ba9c7019a
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
@@ -0,0 +1,46 @@
+//@ edition: 2024
+//@ revisions: classic structural
+//! Test cases for poorly-typed patterns in edition 2024 which are caught by HIR typeck. These must
+//! be separate from cases caught by MIR borrowck or the latter errors may not be emitted.
+#![allow(incomplete_features)]
+#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
+#![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;
+ }
+ if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+ //[classic]~^ ERROR: mismatched types
+ let _: u32 = x;
+ }
+ if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
+ //[classic]~^ ERROR: mismatched types
+ let _: &u32 = x;
+ }
+
+ if let Some(&mut Some(&_)) = &Some(&Some(0)) {
+ //~^ ERROR: mismatched types
+ }
+ if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
+ //~^ ERROR: mismatched types
+ }
+ if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
+ //~^ ERROR: mismatched types
+ }
+ if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
+ //~^ ERROR: mismatched types
+ }
+ if let Some(&mut Some(x)) = &Some(Some(0)) {
+ //~^ ERROR: mismatched types
+ }
+ if let Some(&mut Some(x)) = &Some(Some(0)) {
+ //~^ ERROR: mismatched types
+ }
+}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr
new file mode 100644
index 0000000000000..59d65553fae8f
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr
@@ -0,0 +1,89 @@
+error[E0308]: mismatched types
+ --> $DIR/pattern-errors.rs:10:17
+ |
+LL | if let Some(&mut x) = &mut Some(&0) {
+ | ^^^^^^ ------------- this expression has type `&mut Option<&{integer}>`
+ | |
+ | types differ in mutability
+ |
+ = note: expected reference `&{integer}`
+ found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+ --> $DIR/pattern-errors.rs:10:17
+ |
+LL | if let Some(&mut x) = &mut Some(&0) {
+ | ^^^^^^
+help: consider removing `&mut` from the pattern
+ |
+LL | if let Some(x) = &mut 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
+ |
+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/pattern-errors.rs:34: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/pattern-errors.rs:37: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/pattern-errors.rs:40: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/pattern-errors.rs:43: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: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed
similarity index 73%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed
index e69d169966b52..4f4941975d804 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed
@@ -1,7 +1,11 @@
//@ edition: 2024
//@ run-rustfix
+//@ revisions: classic structural
+//! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts
+//! to bind by mutable reference.
#![allow(incomplete_features)]
-#![feature(ref_pat_eat_one_layer_2024)]
+#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
pub fn main() {
if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) {
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr
similarity index 79%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr
index 8e135b65253fd..6c384a51fac14 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr
@@ -1,5 +1,5 @@
error[E0596]: cannot borrow as mutable inside an `&` pattern
- --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:7:31
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:11:31
|
LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
| - ^
@@ -7,7 +7,7 @@ LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
| help: replace this `&` with `&mut`: `&mut`
error[E0596]: cannot borrow as mutable inside an `&` pattern
- --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:12:31
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
|
LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
| - ^
@@ -15,7 +15,7 @@ LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
| help: replace this `&` with `&mut`: `&mut`
error[E0596]: cannot borrow as mutable inside an `&` pattern
- --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:20:15
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:24:15
|
LL | let &pat!(x) = &mut 0;
| - ^
@@ -23,7 +23,7 @@ LL | let &pat!(x) = &mut 0;
| help: replace this `&` with `&mut`: `&mut`
error[E0596]: cannot borrow as mutable inside an `&` pattern
- --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:24:19
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:19
|
LL | let &(ref mut a, ref mut b) = &mut (true, false);
| - ^
@@ -31,7 +31,7 @@ LL | let &(ref mut a, ref mut b) = &mut (true, false);
| help: replace this `&` with `&mut`: `&mut`
error[E0596]: cannot borrow as mutable inside an `&` pattern
- --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:24:30
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:30
|
LL | let &(ref mut a, ref mut b) = &mut (true, false);
| - ^
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs
similarity index 73%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs
index a300cbcd4df52..b29bff7603f7a 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs
@@ -1,7 +1,11 @@
//@ edition: 2024
//@ run-rustfix
+//@ revisions: classic structural
+//! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts
+//! to bind by mutable reference.
#![allow(incomplete_features)]
-#![feature(ref_pat_eat_one_layer_2024)]
+#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
pub fn main() {
if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed
new file mode 100644
index 0000000000000..4f4941975d804
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed
@@ -0,0 +1,33 @@
+//@ edition: 2024
+//@ run-rustfix
+//@ revisions: classic structural
+//! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts
+//! to bind by mutable reference.
+#![allow(incomplete_features)]
+#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
+
+pub fn main() {
+ if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) {
+ //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+ let _: &mut u8 = x;
+ }
+
+ if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) {
+ //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+ let _: &mut u8 = x;
+ }
+
+ macro_rules! pat {
+ ($var:ident) => { ref mut $var };
+ }
+ let &mut pat!(x) = &mut 0;
+ //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+ let _: &mut u8 = x;
+
+ let &mut (ref mut a, ref mut b) = &mut (true, false);
+ //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+ //~| ERROR: cannot borrow as mutable inside an `&` pattern
+ let _: &mut bool = a;
+ let _: &mut bool = b;
+}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.stderr
new file mode 100644
index 0000000000000..6c384a51fac14
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.stderr
@@ -0,0 +1,43 @@
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:11:31
+ |
+LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
+ | - ^
+ | |
+ | help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
+ |
+LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
+ | - ^
+ | |
+ | help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:24:15
+ |
+LL | let &pat!(x) = &mut 0;
+ | - ^
+ | |
+ | help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:19
+ |
+LL | let &(ref mut a, ref mut b) = &mut (true, false);
+ | - ^
+ | |
+ | help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+ --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:30
+ |
+LL | let &(ref mut a, ref mut b) = &mut (true, false);
+ | - ^
+ | |
+ | help: replace this `&` with `&mut`: `&mut`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs
similarity index 54%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.rs
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs
index afea249ffef0b..9372049a2b283 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs
@@ -1,9 +1,9 @@
//@ run-pass
//@ edition: 2021
-//@ revisions: classic structural both
+//@ revisions: classic structural
#![allow(incomplete_features)]
-#![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))]
+#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
pub fn main() {
if let &Some(Some(x)) = &Some(&mut Some(0)) {
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.rs
similarity index 100%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021_fail.rs
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.rs
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.stderr
similarity index 100%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021_fail.stderr
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.stderr
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/trait-selection-sanity.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/trait-selection-sanity.rs
new file mode 100644
index 0000000000000..cb8fdb489c028
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/trait-selection-sanity.rs
@@ -0,0 +1,30 @@
+//@ edition: 2024
+//@ revisions: with_impl without_impl
+//@[with_impl] run-pass
+//! Sanity check that experimental new pattern typing rules work as expected with trait selection
+
+fn main() {
+ fn generic() -> (R, bool) {
+ R::meow()
+ }
+
+ trait Ref: Sized {
+ fn meow() -> (Self, bool);
+ }
+
+ #[cfg(with_impl)]
+ impl Ref for &'static [(); 0] {
+ fn meow() -> (Self, bool) {
+ (&[], false)
+ }
+ }
+
+ impl Ref for &'static mut [(); 0] {
+ fn meow() -> (Self, bool) {
+ (&mut [], true)
+ }
+ }
+
+ let (&_, b) = generic(); //[without_impl]~ ERROR: the trait bound `&_: main::Ref` is not satisfied [E0277]
+ assert!(!b);
+}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/trait-selection-sanity.without_impl.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/trait-selection-sanity.without_impl.stderr
new file mode 100644
index 0000000000000..83e45221facc7
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/trait-selection-sanity.without_impl.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `&_: main::Ref` is not satisfied
+ --> $DIR/trait-selection-sanity.rs:28:19
+ |
+LL | let (&_, b) = generic();
+ | ^^^^^^^^^ the trait `main::Ref` is not implemented for `&_`
+ |
+ = help: the trait `main::Ref` is implemented for `&'static mut [(); 0]`
+note: required by a bound in `generic`
+ --> $DIR/trait-selection-sanity.rs:7:19
+ |
+LL | fn generic() -> (R, bool) {
+ | ^^^ required by this bound in `generic`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs
similarity index 62%
rename from tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs
index b145446de0a1c..077b52d8f274e 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs
@@ -1,9 +1,11 @@
-//@ run-pass
//@ edition: 2024
-//@ revisions: classic structural both
+//@ revisions: classic structural
+//@ 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)]
-#![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))]
+#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
pub fn main() {
if let Some(Some(&x)) = &Some(&Some(0)) {
@@ -54,35 +56,4 @@ 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;
- }
-
- fn generic() -> (R, bool) {
- R::meow()
- }
-
- trait Ref: Sized {
- fn meow() -> (Self, bool);
- }
-
- impl Ref for &'static [(); 0] {
- fn meow() -> (Self, bool) {
- (&[], false)
- }
- }
-
- impl Ref for &'static mut [(); 0] {
- fn meow() -> (Self, bool) {
- (&mut [], true)
- }
- }
-
- let (&_, b) = generic();
- assert!(!b);
}