From 724b885b4e486a355d176dc78098e131f9c1b2ef Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 3 Feb 2025 01:26:49 -0800 Subject: [PATCH 01/13] pattern migration: move labels out of the suggestion struct --- compiler/rustc_mir_build/src/errors.rs | 10 ++++---- .../rustc_mir_build/src/thir/pattern/mod.rs | 24 +++++++++---------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index af6f33d9cdd4..e8ba4a4b415f 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1097,20 +1097,18 @@ pub(crate) enum MiscPatternSuggestion { #[derive(LintDiagnostic)] #[diag(mir_build_rust_2024_incompatible_pat)] -pub(crate) struct Rust2024IncompatiblePat<'a> { +pub(crate) struct Rust2024IncompatiblePat { #[subdiagnostic] - pub(crate) sugg: Rust2024IncompatiblePatSugg<'a>, + pub(crate) sugg: Rust2024IncompatiblePatSugg, } -pub(crate) struct Rust2024IncompatiblePatSugg<'a> { +pub(crate) struct Rust2024IncompatiblePatSugg { pub(crate) suggestion: Vec<(Span, String)>, pub(crate) ref_pattern_count: usize, pub(crate) binding_mode_count: usize, - /// Labeled spans for subpatterns invalid in Rust 2024. - pub(crate) labels: &'a [(Span, String)], } -impl<'a> Subdiagnostic for Rust2024IncompatiblePatSugg<'a> { +impl Subdiagnostic for Rust2024IncompatiblePatSugg { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 20a728d6d5b2..4b8d0c2fb2f0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -35,7 +35,7 @@ struct PatCtxt<'a, 'tcx> { typeck_results: &'a ty::TypeckResults<'tcx>, /// Used by the Rust 2024 migration lint. - rust_2024_migration_suggestion: Option>, + rust_2024_migration_suggestion: Option, } pub(super) fn pat_from_hir<'a, 'tcx>( @@ -44,25 +44,23 @@ pub(super) fn pat_from_hir<'a, 'tcx>( typeck_results: &'a ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, ) -> Box> { + let migration_labels = typeck_results.rust_2024_migration_desugared_pats().get(pat.hir_id); let mut pcx = PatCtxt { tcx, typing_env, typeck_results, - rust_2024_migration_suggestion: typeck_results - .rust_2024_migration_desugared_pats() - .get(pat.hir_id) - .map(|labels| Rust2024IncompatiblePatSugg { - suggestion: Vec::new(), - ref_pattern_count: 0, - binding_mode_count: 0, - labels: labels.as_slice(), - }), + rust_2024_migration_suggestion: migration_labels.and(Some(Rust2024IncompatiblePatSugg { + suggestion: Vec::new(), + ref_pattern_count: 0, + binding_mode_count: 0, + })), }; let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); - if let Some(sugg) = pcx.rust_2024_migration_suggestion { - let mut spans = MultiSpan::from_spans(sugg.labels.iter().map(|(span, _)| *span).collect()); - for (span, label) in sugg.labels { + if let Some(labels) = migration_labels { + let sugg = pcx.rust_2024_migration_suggestion.expect("suggestion should be present"); + let mut spans = MultiSpan::from_spans(labels.iter().map(|(span, _)| *span).collect()); + for (span, label) in labels { spans.push_span_label(*span, label.clone()); } // If a relevant span is from at least edition 2024, this is a hard error. From bdc6c4d07b5ccb91df396e152deafc3a66b539ab Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 3 Feb 2025 01:50:14 -0800 Subject: [PATCH 02/13] reword pattern migration diagnostic to make sense in all editions This aligns the main error message a bit more with the phrasing in the Edition Guide and provides a bit more information on the labels to (hopefully!) aid in understanding. --- compiler/rustc_hir_typeck/src/pat.rs | 49 +++++++------ compiler/rustc_middle/src/ty/mod.rs | 2 +- .../rustc_middle/src/ty/typeck_results.rs | 22 ++++-- compiler/rustc_mir_build/messages.ftl | 11 ++- compiler/rustc_mir_build/src/errors.rs | 3 + .../rustc_mir_build/src/thir/pattern/mod.rs | 24 ++++--- ...nding-on-inh-ref-errors.classic2024.stderr | 28 ++++---- .../ref-binding-on-inh-ref-errors.rs | 33 +++------ ...inding-on-inh-ref-errors.stable2021.stderr | 6 +- ...ng-on-inh-ref-errors.structural2024.stderr | 66 ++++++++--------- .../migration_lint.fixed | 32 ++++----- .../migration_lint.rs | 32 ++++----- .../migration_lint.stderr | 70 +++++++++---------- .../min_match_ergonomics_fail.rs | 14 ++-- .../min_match_ergonomics_fail.stderr | 28 ++++---- 15 files changed, 224 insertions(+), 196 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c947ecde6560..f5e7b1d9629d 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -804,7 +804,7 @@ 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(_)) => { + BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(def_br_mutbl) = def_br => { // 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() @@ -826,22 +826,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `mut` resets the binding mode on edition <= 2021 self.add_rust_2024_migration_desugared_pat( pat_info.top_info.hir_id, - pat.span, + pat, ident.span, - "requires binding by-value, but the implicit default is by-reference", + def_br_mutbl, ); BindingMode(ByRef::No, Mutability::Mut) } } BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl), BindingMode(ByRef::Yes(_), _) => { - if matches!(def_br, ByRef::Yes(_)) { + if let ByRef::Yes(def_br_mutbl) = def_br { // `ref`/`ref mut` overrides the binding mode on edition <= 2021 self.add_rust_2024_migration_desugared_pat( pat_info.top_info.hir_id, - pat.span, + pat, ident.span, - "cannot override to bind by-reference when that is the implicit default", + def_br_mutbl, ); } user_bind_annot @@ -2378,9 +2378,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_info.binding_mode = ByRef::No; self.add_rust_2024_migration_desugared_pat( pat_info.top_info.hir_id, - pat.span, + pat, inner.span, - "cannot implicitly match against multiple layers of reference", + inh_mut, ) } } @@ -2770,9 +2770,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn add_rust_2024_migration_desugared_pat( &self, pat_id: HirId, - subpat_span: Span, + subpat: &'tcx Pat<'tcx>, cutoff_span: Span, - detailed_label: &str, + def_br_mutbl: Mutability, ) { // Try to trim the span we're labeling to just the `&` or binding mode that's an issue. // If the subpattern's span is is from an expansion, the emitted label will not be trimmed. @@ -2780,23 +2780,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cutoff_span = source_map .span_extend_prev_while(cutoff_span, char::is_whitespace) .unwrap_or(cutoff_span); - // Ensure we use the syntax context and thus edition of `subpat_span`; this will be a hard + // Ensure we use the syntax context and thus edition of `subpat.span`; this will be a hard // error if the subpattern is of edition >= 2024. - let trimmed_span = subpat_span.until(cutoff_span).with_ctxt(subpat_span.ctxt()); + let trimmed_span = subpat.span.until(cutoff_span).with_ctxt(subpat.span.ctxt()); // Only provide a detailed label if the problematic subpattern isn't from an expansion. // In the case that it's from a macro, we'll add a more detailed note in the emitter. - let desc = if subpat_span.from_expansion() { - "default binding mode is reset within expansion" + let desc = if subpat.span.from_expansion() { + "occurs within expansion" } else { - detailed_label + match def_br_mutbl { + Mutability::Not => "default binding mode is `ref`", + Mutability::Mut => "default binding mode is `ref mut`", + } }; - self.typeck_results - .borrow_mut() - .rust_2024_migration_desugared_pats_mut() - .entry(pat_id) - .or_default() - .push((trimmed_span, desc.to_owned())); + let mut typeck_results = self.typeck_results.borrow_mut(); + let mut table = typeck_results.rust_2024_migration_desugared_pats_mut(); + let info = table.entry(pat_id).or_default(); + + info.labels.push((trimmed_span, desc.to_owned())); + if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) { + info.bad_modifiers |= true; + } else { + info.bad_ref_pats |= true; + } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 88eea6101b5f..6fe1502c66dd 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -94,7 +94,7 @@ pub use self::sty::{ pub use self::trait_def::TraitDef; pub use self::typeck_results::{ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity, - TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind, + Rust2024IncompatiblePatInfo, TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind, }; pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index f94f52e4f618..0dbbfee0cfa0 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -73,9 +73,9 @@ pub struct TypeckResults<'tcx> { /// Stores the actual binding mode for all instances of [`BindingMode`]. pat_binding_modes: ItemLocalMap, - /// Top-level patterns whose match ergonomics need to be desugared by the Rust 2021 -> 2024 - /// migration lint. Problematic subpatterns are stored in the `Vec` for the lint to highlight. - rust_2024_migration_desugared_pats: ItemLocalMap>, + /// Top-level patterns incompatible with Rust 2024's match ergonomics. These will be translated + /// to a form valid in all Editions, either as a lint diagnostic or hard error. + rust_2024_migration_desugared_pats: ItemLocalMap, /// Stores the types which were implicitly dereferenced in pattern binding modes /// for later usage in THIR lowering. For example, @@ -420,7 +420,7 @@ impl<'tcx> TypeckResults<'tcx> { pub fn rust_2024_migration_desugared_pats( &self, - ) -> LocalTableInContext<'_, Vec<(Span, String)>> { + ) -> LocalTableInContext<'_, Rust2024IncompatiblePatInfo> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.rust_2024_migration_desugared_pats, @@ -429,7 +429,7 @@ impl<'tcx> TypeckResults<'tcx> { pub fn rust_2024_migration_desugared_pats_mut( &mut self, - ) -> LocalTableInContextMut<'_, Vec<(Span, String)>> { + ) -> LocalTableInContextMut<'_, Rust2024IncompatiblePatInfo> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.rust_2024_migration_desugared_pats, @@ -811,3 +811,15 @@ impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> { } } } + +/// Information on a pattern incompatible with Rust 2024, for use by the error/migration diagnostic +/// emitted during THIR construction. +#[derive(TyEncodable, TyDecodable, Debug, HashStable, Default)] +pub struct Rust2024IncompatiblePatInfo { + /// Labels for subpatterns incompatible with Rust 2024. + pub labels: Vec<(Span, String)>, + /// Whether any binding modifiers occur under a non-`move` default binding mode. + pub bad_modifiers: bool, + /// Whether any `&` or `&mut` patterns occur under a non-`move` default binding mode. + pub bad_ref_pats: bool, +} diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 3cf3c3328938..fae159103e70 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -285,7 +285,16 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future -mir_build_rust_2024_incompatible_pat = this pattern relies on behavior which may change in edition 2024 +mir_build_rust_2024_incompatible_pat = {$bad_modifiers -> + *[true] binding modifiers{$bad_ref_pats -> + *[true] {" "}and reference patterns + [false] {""} + } + [false] reference patterns + } may only be written when the default binding mode is `move`{$is_hard_error -> + *[true] {""} + [false] {" "}in Rust 2024 + } mir_build_static_in_pattern = statics cannot be referenced in patterns .label = can't be used in patterns diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index e8ba4a4b415f..0289a6c4073a 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1100,6 +1100,9 @@ pub(crate) enum MiscPatternSuggestion { pub(crate) struct Rust2024IncompatiblePat { #[subdiagnostic] pub(crate) sugg: Rust2024IncompatiblePatSugg, + pub(crate) bad_modifiers: bool, + pub(crate) bad_ref_pats: bool, + pub(crate) is_hard_error: bool, } pub(crate) struct Rust2024IncompatiblePatSugg { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 4b8d0c2fb2f0..f12234723ec0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -44,12 +44,12 @@ pub(super) fn pat_from_hir<'a, 'tcx>( typeck_results: &'a ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, ) -> Box> { - let migration_labels = typeck_results.rust_2024_migration_desugared_pats().get(pat.hir_id); + let migration_info = typeck_results.rust_2024_migration_desugared_pats().get(pat.hir_id); let mut pcx = PatCtxt { tcx, typing_env, typeck_results, - rust_2024_migration_suggestion: migration_labels.and(Some(Rust2024IncompatiblePatSugg { + rust_2024_migration_suggestion: migration_info.and(Some(Rust2024IncompatiblePatSugg { suggestion: Vec::new(), ref_pattern_count: 0, binding_mode_count: 0, @@ -57,10 +57,10 @@ pub(super) fn pat_from_hir<'a, 'tcx>( }; let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); - if let Some(labels) = migration_labels { + if let Some(info) = migration_info { let sugg = pcx.rust_2024_migration_suggestion.expect("suggestion should be present"); - let mut spans = MultiSpan::from_spans(labels.iter().map(|(span, _)| *span).collect()); - for (span, label) in labels { + let mut spans = MultiSpan::from_spans(info.labels.iter().map(|(span, _)| *span).collect()); + for (span, label) in &info.labels { spans.push_span_label(*span, label.clone()); } // If a relevant span is from at least edition 2024, this is a hard error. @@ -68,10 +68,13 @@ pub(super) fn pat_from_hir<'a, 'tcx>( if is_hard_error { let mut err = tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat); - if let Some(info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible { + if let Some(lint_info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible { // provide the same reference link as the lint - err.note(format!("for more information, see {}", info.reference)); + err.note(format!("for more information, see {}", lint_info.reference)); } + err.arg("bad_modifiers", info.bad_modifiers); + err.arg("bad_ref_pats", info.bad_ref_pats); + err.arg("is_hard_error", true); err.subdiagnostic(sugg); err.emit(); } else { @@ -79,7 +82,12 @@ pub(super) fn pat_from_hir<'a, 'tcx>( lint::builtin::RUST_2024_INCOMPATIBLE_PAT, pat.hir_id, spans, - Rust2024IncompatiblePat { sugg }, + Rust2024IncompatiblePat { + sugg, + bad_modifiers: info.bad_modifiers, + bad_ref_pats: info.bad_ref_pats, + is_hard_error, + }, ); } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr index 70cdcbd62eb0..fbe1164c6250 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/ref-binding-on-inh-ref-errors.rs:60:10 + --> $DIR/ref-binding-on-inh-ref-errors.rs:54:10 | LL | let [&mut ref x] = &[&mut 0]; | ^^^^^ @@ -10,11 +10,11 @@ help: replace this `&mut` pattern with `&` LL | let [&ref x] = &[&mut 0]; | ~ -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; - | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | ^^^^^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -23,16 +23,16 @@ LL | let &[ref mut x] = &[0]; | + error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; | ^^^^^^^^^ cannot borrow as mutable -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10 | LL | let [ref x] = &[0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -40,11 +40,11 @@ help: make the implied reference pattern explicit LL | let &[ref x] = &[0]; | + -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:88:10 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10 | LL | let [ref x] = &mut [0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -52,11 +52,11 @@ help: make the implied reference pattern explicit LL | let &mut [ref x] = &mut [0]; | ++++ -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:93:10 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 | LL | let [ref mut x] = &mut [0]; - | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | ^^^^^^^ default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs index 4c88c0c63ae5..4e048570c33c 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs @@ -13,26 +13,22 @@ /// The eat-outer variant eats the inherited reference, so binding with `ref` isn't a problem. fn errors_from_eating_the_real_reference() { let [&ref x] = &[&0]; - //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural2024]~| cannot override to bind by-reference when that is the implicit default + //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(stable2021)] let _: &u32 = x; #[cfg(classic2024)] let _: &&u32 = x; let [&ref x] = &mut [&0]; - //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural2024]~| cannot override to bind by-reference when that is the implicit default + //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(stable2021)] let _: &u32 = x; #[cfg(classic2024)] let _: &&u32 = x; let [&mut ref x] = &mut [&mut 0]; - //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural2024]~| cannot override to bind by-reference when that is the implicit default + //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(stable2021)] let _: &u32 = x; #[cfg(classic2024)] let _: &&mut u32 = x; let [&mut ref mut x] = &mut [&mut 0]; - //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural2024]~| cannot override to bind by-reference when that is the implicit default + //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(stable2021)] let _: &mut u32 = x; #[cfg(classic2024)] let _: &mut &mut u32 = x; } @@ -43,15 +39,13 @@ fn errors_from_eating_the_real_reference_caught_in_hir_typeck_on_stable() { let [&ref x] = &[&mut 0]; //[stable2021]~^ ERROR: mismatched types //[stable2021]~| types differ in mutability - //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural2024]~| cannot override to bind by-reference when that is the implicit default + //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(classic2024)] let _: &&mut u32 = x; let [&ref x] = &mut [&mut 0]; //[stable2021]~^ ERROR: mismatched types //[stable2021]~| types differ in mutability - //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural2024]~| cannot override to bind by-reference when that is the implicit default + //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(classic2024)] let _: &&mut u32 = x; } @@ -60,8 +54,7 @@ fn errors_dependent_on_eating_order_caught_in_hir_typeck_when_eating_outer() { let [&mut ref x] = &[&mut 0]; //[classic2024]~^ ERROR: mismatched types //[classic2024]~| cannot match inherited `&` with `&mut` pattern - //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural2024]~| cannot override to bind by-reference when that is the implicit default + //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(stable2021)] let _: &u32 = x; } @@ -73,25 +66,21 @@ fn errors_dependent_on_eating_order_caught_in_hir_typeck_when_eating_outer() { fn borrowck_errors_in_old_editions() { let [ref mut x] = &[0]; //~^ ERROR: cannot borrow data in a `&` reference as mutable - //[classic2024,structural2024]~| ERROR: this pattern relies on behavior which may change in edition 2024 - //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + //[classic2024,structural2024]~| ERROR: binding modifiers may only be written when the default binding mode is `move` } /// The remaining tests are purely for testing `ref` bindings in the presence of an inherited /// reference. These should always fail on edition 2024 and succeed on edition 2021. pub fn main() { let [ref x] = &[0]; - //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(stable2021)] let _: &u32 = x; let [ref x] = &mut [0]; - //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(stable2021)] let _: &u32 = x; let [ref mut x] = &mut [0]; - //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move` #[cfg(stable2021)] let _: &mut u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr index a21e4bb5b8f8..26095d846057 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/ref-binding-on-inh-ref-errors.rs:43:10 + --> $DIR/ref-binding-on-inh-ref-errors.rs:39:10 | LL | let [&ref x] = &[&mut 0]; | ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` @@ -15,7 +15,7 @@ LL + let [ref x] = &[&mut 0]; | error[E0308]: mismatched types - --> $DIR/ref-binding-on-inh-ref-errors.rs:50:10 + --> $DIR/ref-binding-on-inh-ref-errors.rs:45:10 | LL | let [&ref x] = &mut [&mut 0]; | ^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` @@ -31,7 +31,7 @@ LL + let [ref x] = &mut [&mut 0]; | error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; | ^^^^^^^^^ cannot borrow as mutable diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr index ee2c831bfcc8..f355b7c61a26 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr @@ -1,8 +1,8 @@ -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` --> $DIR/ref-binding-on-inh-ref-errors.rs:15:11 | LL | let [&ref x] = &[&0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -10,11 +10,11 @@ help: make the implied reference pattern explicit LL | let &[&ref x] = &[&0]; | + -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:21:11 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:20:11 | LL | let [&ref x] = &mut [&0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -22,11 +22,11 @@ help: make the implied reference pattern explicit LL | let &mut [&ref x] = &mut [&0]; | ++++ -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:27:15 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:25:15 | LL | let [&mut ref x] = &mut [&mut 0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -34,11 +34,11 @@ help: make the implied reference pattern explicit LL | let &mut [&mut ref x] = &mut [&mut 0]; | ++++ -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:33:15 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:30:15 | LL | let [&mut ref mut x] = &mut [&mut 0]; - | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | ^^^^^^^ default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -46,11 +46,11 @@ help: make the implied reference pattern explicit LL | let &mut [&mut ref mut x] = &mut [&mut 0]; | ++++ -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:43:11 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:39:11 | LL | let [&ref x] = &[&mut 0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -58,11 +58,11 @@ help: make the implied reference pattern explicit LL | let &[&ref x] = &[&mut 0]; | + -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:50:11 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:45:11 | LL | let [&ref x] = &mut [&mut 0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -70,11 +70,11 @@ help: make the implied reference pattern explicit LL | let &mut [&ref x] = &mut [&mut 0]; | ++++ -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:60:15 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:54:15 | LL | let [&mut ref x] = &[&mut 0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -82,11 +82,11 @@ help: make the implied reference pattern explicit LL | let &[&mut ref x] = &[&mut 0]; | + -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; - | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | ^^^^^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -95,16 +95,16 @@ LL | let &[ref mut x] = &[0]; | + error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; | ^^^^^^^^^ cannot borrow as mutable -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10 | LL | let [ref x] = &[0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -112,11 +112,11 @@ help: make the implied reference pattern explicit LL | let &[ref x] = &[0]; | + -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:88:10 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10 | LL | let [ref x] = &mut [0]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -124,11 +124,11 @@ help: make the implied reference pattern explicit LL | let &mut [ref x] = &mut [0]; | ++++ -error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:93:10 +error: binding modifiers may only be written when the default binding mode is `move` + --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 | LL | let [ref mut x] = &mut [0]; - | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | ^^^^^^^ default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index e2b2c9876104..fbca9149bc3a 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -23,22 +23,22 @@ fn main() { assert_type_eq(x, &mut 0u8); let &Foo(mut x) = &Foo(0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(mut x) = &mut Foo(0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(ref x) = &Foo(0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let &mut Foo(ref x) = &mut Foo(0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); @@ -55,22 +55,22 @@ fn main() { assert_type_eq(x, &0u8); let &Foo(&x) = &Foo(&0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(&mut x) = &Foo(&mut 0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&x) = &mut Foo(&0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&mut x) = &mut Foo(&mut 0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); @@ -79,25 +79,25 @@ fn main() { } if let &&&&&Some(&x) = &&&&&Some(&0u8) { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -109,20 +109,20 @@ fn main() { } let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { @@ -135,7 +135,7 @@ fn main() { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. &(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` assert_type_eq(x, 0u32); assert_type_eq(y, 0u32); } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index 098540adfa2c..b9428ab8c8f7 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -23,22 +23,22 @@ fn main() { assert_type_eq(x, &mut 0u8); let Foo(mut x) = &Foo(0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(mut x) = &mut Foo(0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(ref x) = &Foo(0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let Foo(ref x) = &mut Foo(0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); @@ -55,22 +55,22 @@ fn main() { assert_type_eq(x, &0u8); let Foo(&x) = &Foo(&0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &Foo(&mut 0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&x) = &mut Foo(&0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &mut Foo(&mut 0); - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); @@ -79,25 +79,25 @@ fn main() { } if let Some(&x) = &&&&&Some(&0u8) { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut x) = &&&&&Some(&mut 0u8) { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&x) = &&&&&mut Some(&0u8) { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -109,20 +109,20 @@ fn main() { } let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { @@ -135,7 +135,7 @@ fn main() { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - //~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` assert_type_eq(x, 0u32); assert_type_eq(y, 0u32); } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 83346b9dd4a8..8f675d2fb570 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -1,8 +1,8 @@ -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:25:13 | LL | let Foo(mut x) = &Foo(0); - | ^^^ requires binding by-value, but the implicit default is by-reference + | ^^^ default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -16,11 +16,11 @@ help: make the implied reference pattern explicit LL | let &Foo(mut x) = &Foo(0); | + -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:30:13 | LL | let Foo(mut x) = &mut Foo(0); - | ^^^ requires binding by-value, but the implicit default is by-reference + | ^^^ default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -29,11 +29,11 @@ help: make the implied reference pattern explicit LL | let &mut Foo(mut x) = &mut Foo(0); | ++++ -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:35:13 | LL | let Foo(ref x) = &Foo(0); - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -42,11 +42,11 @@ help: make the implied reference pattern explicit LL | let &Foo(ref x) = &Foo(0); | + -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:40:13 | LL | let Foo(ref x) = &mut Foo(0); - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -55,11 +55,11 @@ help: make the implied reference pattern explicit LL | let &mut Foo(ref x) = &mut Foo(0); | ++++ -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:57:13 | LL | let Foo(&x) = &Foo(&0); - | ^ cannot implicitly match against multiple layers of reference + | ^ default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -68,11 +68,11 @@ help: make the implied reference pattern explicit LL | let &Foo(&x) = &Foo(&0); | + -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:62:13 | LL | let Foo(&mut x) = &Foo(&mut 0); - | ^^^^ cannot implicitly match against multiple layers of reference + | ^^^^ default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -81,11 +81,11 @@ help: make the implied reference pattern explicit LL | let &Foo(&mut x) = &Foo(&mut 0); | + -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:67:13 | LL | let Foo(&x) = &mut Foo(&0); - | ^ cannot implicitly match against multiple layers of reference + | ^ default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -94,11 +94,11 @@ help: make the implied reference pattern explicit LL | let &mut Foo(&x) = &mut Foo(&0); | ++++ -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:72:13 | LL | let Foo(&mut x) = &mut Foo(&mut 0); - | ^^^^ cannot implicitly match against multiple layers of reference + | ^^^^ default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -107,11 +107,11 @@ help: make the implied reference pattern explicit LL | let &mut Foo(&mut x) = &mut Foo(&mut 0); | ++++ -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:81:17 | LL | if let Some(&x) = &&&&&Some(&0u8) { - | ^ cannot implicitly match against multiple layers of reference + | ^ default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -120,11 +120,11 @@ help: make the implied reference patterns explicit LL | if let &&&&&Some(&x) = &&&&&Some(&0u8) { | +++++ -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:87:17 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { - | ^^^^ cannot implicitly match against multiple layers of reference + | ^^^^ default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -133,11 +133,11 @@ help: make the implied reference patterns explicit LL | if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { | +++++ -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:93:17 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { - | ^ cannot implicitly match against multiple layers of reference + | ^ default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -146,11 +146,11 @@ help: make the implied reference patterns explicit LL | if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { | ++++++++ -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:99:17 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - | ^^^^ cannot implicitly match against multiple layers of reference + | ^^^^ default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -159,11 +159,11 @@ help: make the implied reference patterns and variable binding mode explicit LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { | ++++ ++++ +++++++ -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:111:21 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - | ^^^ requires binding by-value, but the implicit default is by-reference + | ^^^ default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -172,13 +172,13 @@ help: make the implied reference pattern and variable binding modes explicit LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; | + +++ +++ -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:117:21 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - | ^ ^^^ cannot override to bind by-reference when that is the implicit default + | ^ ^^^ default binding mode is `ref` | | - | cannot implicitly match against multiple layers of reference + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -187,13 +187,13 @@ help: make the implied reference pattern and variable binding mode explicit LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; | + +++ -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:124:24 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - | ^ ^ cannot implicitly match against multiple layers of reference + | ^ ^ default binding mode is `ref` | | - | cannot implicitly match against multiple layers of reference + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -202,13 +202,13 @@ help: make the implied reference patterns and variable binding mode explicit LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = | + + + +++ -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` --> $DIR/migration_lint.rs:137:15 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ default binding mode is reset within expansion + | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within expansion | | - | requires binding by-value, but the implicit default is by-reference + | default binding mode is `ref` | = note: for more information, see = note: this error originates in the macro `migration_lint_macros::mixed_edition_pat` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs index 5ba554fc6e5a..4dc04d90aaf5 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs @@ -21,17 +21,17 @@ macro_rules! test_pat_on_type { } test_pat_on_type![(&x,): &(T,)]; //~ ERROR mismatched types -test_pat_on_type![(&x,): &(&T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 +test_pat_on_type![(&x,): &(&T,)]; //~ ERROR reference patterns may only be written when the default binding mode is `move` test_pat_on_type![(&x,): &(&mut T,)]; //~ ERROR mismatched types test_pat_on_type![(&mut x,): &(&T,)]; //~ ERROR mismatched types -test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 +test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR reference patterns may only be written when the default binding mode is `move` test_pat_on_type![(&x,): &&mut &(T,)]; //~ ERROR mismatched types test_pat_on_type![Foo { f: (&x,) }: Foo]; //~ ERROR mismatched types test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; //~ ERROR mismatched types -test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR this pattern relies on behavior which may change in edition 2024 -test_pat_on_type![(mut x,): &(T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 -test_pat_on_type![(ref x,): &(T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 -test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 +test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR reference patterns may only be written when the default binding mode is `move` +test_pat_on_type![(mut x,): &(T,)]; //~ ERROR binding modifiers may only be written when the default binding mode is `move` +test_pat_on_type![(ref x,): &(T,)]; //~ ERROR binding modifiers may only be written when the default binding mode is `move` +test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR binding modifiers may only be written when the default binding mode is `move` fn get() -> X { unimplemented!() @@ -40,6 +40,6 @@ fn get() -> X { // Make sure this works even when the underlying type is inferred. This test passes on rust stable. fn infer() -> X { match &get() { - (&x,) => x, //~ ERROR this pattern relies on behavior which may change in edition 2024 + (&x,) => x, //~ ERROR reference patterns may only be written when the default binding mode is `move` } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index affdca1d4490..89868a1f3337 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -99,11 +99,11 @@ LL - test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; LL + test_pat_on_type![Foo { f: (x,) }: &mut Foo]; | -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` --> $DIR/min_match_ergonomics_fail.rs:24:20 | LL | test_pat_on_type![(&x,): &(&T,)]; - | ^ cannot implicitly match against multiple layers of reference + | ^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -111,11 +111,11 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&(&x,): &(&T,)]; | + -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` --> $DIR/min_match_ergonomics_fail.rs:27:20 | LL | test_pat_on_type![(&mut x,): &(&mut T,)]; - | ^^^^ cannot implicitly match against multiple layers of reference + | ^^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -123,11 +123,11 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&(&mut x,): &(&mut T,)]; | + -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` --> $DIR/min_match_ergonomics_fail.rs:31:28 | LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; - | ^ cannot implicitly match against multiple layers of reference + | ^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -135,11 +135,11 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&Foo { f: &(x,) }: &Foo]; | + -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` --> $DIR/min_match_ergonomics_fail.rs:32:20 | LL | test_pat_on_type![(mut x,): &(T,)]; - | ^^^ requires binding by-value, but the implicit default is by-reference + | ^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -147,11 +147,11 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&(mut x,): &(T,)]; | + -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` --> $DIR/min_match_ergonomics_fail.rs:33:20 | LL | test_pat_on_type![(ref x,): &(T,)]; - | ^^^ cannot override to bind by-reference when that is the implicit default + | ^^^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -159,11 +159,11 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&(ref x,): &(T,)]; | + -error: this pattern relies on behavior which may change in edition 2024 +error: binding modifiers may only be written when the default binding mode is `move` --> $DIR/min_match_ergonomics_fail.rs:34:20 | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; - | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | ^^^^^^^ default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -171,11 +171,11 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&mut (ref mut x,): &mut (T,)]; | ++++ -error: this pattern relies on behavior which may change in edition 2024 +error: reference patterns may only be written when the default binding mode is `move` --> $DIR/min_match_ergonomics_fail.rs:43:10 | LL | (&x,) => x, - | ^ cannot implicitly match against multiple layers of reference + | ^ default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit From bbe40acb9a192ab2afec1f8adc45c3b72925caf2 Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 3 Feb 2025 19:56:46 -0800 Subject: [PATCH 03/13] use more specific wording for subpatterns from macro expansions --- compiler/rustc_hir_typeck/src/pat.rs | 5 ++++- .../rfc-3627-match-ergonomics-2024/migration_lint.stderr | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f5e7b1d9629d..1970040ec86b 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2787,7 +2787,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only provide a detailed label if the problematic subpattern isn't from an expansion. // In the case that it's from a macro, we'll add a more detailed note in the emitter. let desc = if subpat.span.from_expansion() { - "occurs within expansion" + // NB: This wording assumes the only expansions that can produce problematic reference + // patterns and bindings are macros. If a desugaring or AST pass is added that can do + // so, we may want to inspect the span's source callee or macro backtrace. + "occurs within macro expansion" } else { match def_br_mutbl { Mutability::Not => "default binding mode is `ref`", diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 8f675d2fb570..53558e6891e0 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -206,7 +206,7 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:137:15 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within expansion + | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion | | | default binding mode is `ref` | From 9202001c1c5c3bd9c1fce522744c8620e17d791a Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 3 Feb 2025 22:06:42 -0800 Subject: [PATCH 04/13] add tests for label formatting --- .../migration_lint.fixed | 9 ++++++ .../migration_lint.rs | 9 ++++++ .../migration_lint.stderr | 30 ++++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index fbca9149bc3a..911b42c9ddfe 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -141,4 +141,13 @@ fn main() { } _ => {} } + + let &mut [&mut &[ref a]] = &mut [&mut &[0]]; + //~^ ERROR: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + + let &[&(_)] = &[&0]; + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index b9428ab8c8f7..bf5fd780404b 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -141,4 +141,13 @@ fn main() { } _ => {} } + + let [&mut [ref a]] = &mut [&mut &[0]]; + //~^ ERROR: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + + let [&(_)] = &[&0]; + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 53558e6891e0..0a9d2cf223a9 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -217,5 +217,33 @@ help: make the implied reference pattern explicit LL | &(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { | + -error: aborting due to 16 previous errors +error: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:145:10 + | +LL | let [&mut [ref a]] = &mut [&mut &[0]]; + | ^^^^ ^^^ default binding mode is `ref` + | | + | default binding mode is `ref mut` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +help: make the implied reference patterns explicit + | +LL | let &mut [&mut &[ref a]] = &mut [&mut &[0]]; + | ++++ + + +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:150:10 + | +LL | let [&(_)] = &[&0]; + | ^^ default binding mode is `ref` + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[&(_)] = &[&0]; + | + + +error: aborting due to 18 previous errors From 4331f55b729d1a41004305f85dfe4dbbcec3ee3f Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 3 Feb 2025 22:18:00 -0800 Subject: [PATCH 05/13] highlight the whole problem subpattern when pointing out the default binding mode --- compiler/rustc_hir_typeck/src/pat.rs | 35 ++++--- .../rustc_middle/src/ty/typeck_results.rs | 6 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 4 +- ...nding-on-inh-ref-errors.classic2024.stderr | 20 +++- ...ng-on-inh-ref-errors.structural2024.stderr | 55 ++++++++--- .../migration_lint.stderr | 94 ++++++++++++++----- .../min_match_ergonomics_fail.stderr | 35 +++++-- 7 files changed, 189 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 1970040ec86b..6b0a87f1aefb 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2784,29 +2784,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // error if the subpattern is of edition >= 2024. let trimmed_span = subpat.span.until(cutoff_span).with_ctxt(subpat.span.ctxt()); + let mut typeck_results = self.typeck_results.borrow_mut(); + let mut table = typeck_results.rust_2024_migration_desugared_pats_mut(); + let info = table.entry(pat_id).or_default(); + + info.primary_spans.push(trimmed_span); + // Only provide a detailed label if the problematic subpattern isn't from an expansion. // In the case that it's from a macro, we'll add a more detailed note in the emitter. - let desc = if subpat.span.from_expansion() { + let from_expansion = subpat.span.from_expansion(); + let primary_label = if from_expansion { // NB: This wording assumes the only expansions that can produce problematic reference // patterns and bindings are macros. If a desugaring or AST pass is added that can do // so, we may want to inspect the span's source callee or macro backtrace. "occurs within macro expansion" } else { - match def_br_mutbl { - Mutability::Not => "default binding mode is `ref`", - Mutability::Mut => "default binding mode is `ref mut`", + if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) { + info.bad_modifiers |= true; + "this binding modifier" + } else { + info.bad_ref_pats |= true; + "this reference pattern" } }; + info.span_labels.push((trimmed_span, primary_label.to_owned())); - let mut typeck_results = self.typeck_results.borrow_mut(); - let mut table = typeck_results.rust_2024_migration_desugared_pats_mut(); - let info = table.entry(pat_id).or_default(); - - info.labels.push((trimmed_span, desc.to_owned())); - if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) { - info.bad_modifiers |= true; - } else { - info.bad_ref_pats |= true; + if !from_expansion { + // Add a secondary label covering the whole pattern noting the default binding mode + let def_br_desc = match def_br_mutbl { + Mutability::Not => "default binding mode is `ref`", + Mutability::Mut => "default binding mode is `ref mut`", + }; + info.span_labels.push((subpat.span, def_br_desc.to_owned())); } } } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 0dbbfee0cfa0..a75a7fcd5695 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -816,8 +816,10 @@ impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> { /// emitted during THIR construction. #[derive(TyEncodable, TyDecodable, Debug, HashStable, Default)] pub struct Rust2024IncompatiblePatInfo { - /// Labels for subpatterns incompatible with Rust 2024. - pub labels: Vec<(Span, String)>, + /// Spans for `&`s, `&mut`s, and binding modifiers incompatible with Rust 2024. + pub primary_spans: Vec, + /// Labels for the primary spans and their patterns, to provide additional context. + pub span_labels: Vec<(Span, String)>, /// Whether any binding modifiers occur under a non-`move` default binding mode. pub bad_modifiers: bool, /// Whether any `&` or `&mut` patterns occur under a non-`move` default binding mode. diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index f12234723ec0..cdabd283150d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -59,8 +59,8 @@ pub(super) fn pat_from_hir<'a, 'tcx>( debug!("pat_from_hir({:?}) = {:?}", pat, result); if let Some(info) = migration_info { let sugg = pcx.rust_2024_migration_suggestion.expect("suggestion should be present"); - let mut spans = MultiSpan::from_spans(info.labels.iter().map(|(span, _)| *span).collect()); - for (span, label) in &info.labels { + let mut spans = MultiSpan::from_spans(info.primary_spans.clone()); + for (span, label) in &info.span_labels { spans.push_span_label(*span, label.clone()); } // If a relevant span is from at least edition 2024, this is a hard error. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr index fbe1164c6250..d4313f915df3 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr @@ -14,7 +14,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; - | ^^^^^^^ default binding mode is `ref` + | ^^^^^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -32,7 +35,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10 | LL | let [ref x] = &[0]; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -44,7 +50,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10 | LL | let [ref x] = &mut [0]; - | ^^^ default binding mode is `ref mut` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -56,7 +65,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 | LL | let [ref mut x] = &mut [0]; - | ^^^^^^^ default binding mode is `ref mut` + | ^^^^^^^-- + | | + | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr index f355b7c61a26..8edb6511f230 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr @@ -2,7 +2,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:15:11 | LL | let [&ref x] = &[&0]; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -14,7 +17,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:20:11 | LL | let [&ref x] = &mut [&0]; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -26,7 +32,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:25:15 | LL | let [&mut ref x] = &mut [&mut 0]; - | ^^^ default binding mode is `ref mut` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -38,7 +47,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:30:15 | LL | let [&mut ref mut x] = &mut [&mut 0]; - | ^^^^^^^ default binding mode is `ref mut` + | ^^^^^^^-- + | | + | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -50,7 +62,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:39:11 | LL | let [&ref x] = &[&mut 0]; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -62,7 +77,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:45:11 | LL | let [&ref x] = &mut [&mut 0]; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -74,7 +92,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:54:15 | LL | let [&mut ref x] = &[&mut 0]; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -86,7 +107,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; - | ^^^^^^^ default binding mode is `ref` + | ^^^^^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -104,7 +128,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10 | LL | let [ref x] = &[0]; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -116,7 +143,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10 | LL | let [ref x] = &mut [0]; - | ^^^ default binding mode is `ref mut` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -128,7 +158,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 | LL | let [ref mut x] = &mut [0]; - | ^^^^^^^ default binding mode is `ref mut` + | ^^^^^^^-- + | | + | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 0a9d2cf223a9..cbb94a52878e 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -2,7 +2,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:25:13 | LL | let Foo(mut x) = &Foo(0); - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -20,7 +23,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:30:13 | LL | let Foo(mut x) = &mut Foo(0); - | ^^^ default binding mode is `ref mut` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -33,7 +39,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:35:13 | LL | let Foo(ref x) = &Foo(0); - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -46,7 +55,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:40:13 | LL | let Foo(ref x) = &mut Foo(0); - | ^^^ default binding mode is `ref mut` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -59,7 +71,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:57:13 | LL | let Foo(&x) = &Foo(&0); - | ^ default binding mode is `ref` + | ^- + | | + | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -72,7 +87,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:62:13 | LL | let Foo(&mut x) = &Foo(&mut 0); - | ^^^^ default binding mode is `ref` + | ^^^^-- + | | + | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -85,7 +103,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:67:13 | LL | let Foo(&x) = &mut Foo(&0); - | ^ default binding mode is `ref mut` + | ^- + | | + | this reference pattern + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -98,7 +119,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:72:13 | LL | let Foo(&mut x) = &mut Foo(&mut 0); - | ^^^^ default binding mode is `ref mut` + | ^^^^-- + | | + | this reference pattern + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -111,7 +135,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:81:17 | LL | if let Some(&x) = &&&&&Some(&0u8) { - | ^ default binding mode is `ref` + | ^- + | | + | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -124,7 +151,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:87:17 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { - | ^^^^ default binding mode is `ref` + | ^^^^-- + | | + | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -137,7 +167,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:93:17 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { - | ^ default binding mode is `ref` + | ^- + | | + | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -150,7 +183,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:99:17 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - | ^^^^ default binding mode is `ref mut` + | ^^^^-------------- + | | + | this reference pattern + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -163,7 +199,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:111:21 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -176,8 +215,11 @@ error: binding modifiers and reference patterns may only be written when the def --> $DIR/migration_lint.rs:117:21 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - | ^ ^^^ default binding mode is `ref` - | | + | ^- ^^^-- + | | | + | | this binding modifier + | | default binding mode is `ref` + | this reference pattern | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 @@ -191,8 +233,11 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:124:24 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - | ^ ^ default binding mode is `ref` - | | + | ^------- ^- + | | | + | | this reference pattern + | | default binding mode is `ref` + | this reference pattern | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 @@ -206,8 +251,9 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:137:15 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion + | ^^^-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion | | + | this binding modifier | default binding mode is `ref` | = note: for more information, see @@ -221,8 +267,11 @@ error: binding modifiers and reference patterns may only be written when the def --> $DIR/migration_lint.rs:145:10 | LL | let [&mut [ref a]] = &mut [&mut &[0]]; - | ^^^^ ^^^ default binding mode is `ref` - | | + | ^^^^--^^^--- + | | | + | | this binding modifier + | | default binding mode is `ref` + | this reference pattern | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 @@ -236,7 +285,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:150:10 | LL | let [&(_)] = &[&0]; - | ^^ default binding mode is `ref` + | ^^-- + | | + | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index 89868a1f3337..ce93199b1864 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -103,7 +103,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:24:20 | LL | test_pat_on_type![(&x,): &(&T,)]; - | ^ default binding mode is `ref` + | ^- + | | + | this reference pattern + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -115,7 +118,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:27:20 | LL | test_pat_on_type![(&mut x,): &(&mut T,)]; - | ^^^^ default binding mode is `ref` + | ^^^^-- + | | + | this reference pattern + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -127,7 +133,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:31:28 | LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; - | ^ default binding mode is `ref` + | ^---- + | | + | this reference pattern + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -139,7 +148,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/min_match_ergonomics_fail.rs:32:20 | LL | test_pat_on_type![(mut x,): &(T,)]; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -151,7 +163,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/min_match_ergonomics_fail.rs:33:20 | LL | test_pat_on_type![(ref x,): &(T,)]; - | ^^^ default binding mode is `ref` + | ^^^-- + | | + | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -163,7 +178,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/min_match_ergonomics_fail.rs:34:20 | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; - | ^^^^^^^ default binding mode is `ref mut` + | ^^^^^^^-- + | | + | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -175,7 +193,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:43:10 | LL | (&x,) => x, - | ^ default binding mode is `ref` + | ^- + | | + | this reference pattern + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit From 203d3109d8e96a6a4075205e836216d7cd281d5b Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 4 Feb 2025 03:18:10 -0800 Subject: [PATCH 06/13] experimentally label the spans for default binding modes --- compiler/rustc_hir_typeck/src/pat.rs | 21 +-- .../rustc_middle/src/ty/typeck_results.rs | 6 +- compiler/rustc_mir_build/src/errors.rs | 6 + .../rustc_mir_build/src/thir/pattern/mod.rs | 123 ++++++++++---- ...nding-on-inh-ref-errors.classic2024.stderr | 32 ++-- ...ng-on-inh-ref-errors.structural2024.stderr | 88 +++++----- .../migration_lint.stderr | 155 +++++++++--------- .../min_match_ergonomics_fail.stderr | 56 +++---- 8 files changed, 264 insertions(+), 223 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 6b0a87f1aefb..672e81a4c2aa 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -804,7 +804,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Determine the binding mode... let bm = match user_bind_annot { - BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(def_br_mutbl) = def_br => { + 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() @@ -828,20 +828,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_info.top_info.hir_id, pat, ident.span, - def_br_mutbl, ); BindingMode(ByRef::No, Mutability::Mut) } } BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl), BindingMode(ByRef::Yes(_), _) => { - if let ByRef::Yes(def_br_mutbl) = def_br { + if matches!(def_br, ByRef::Yes(_)) { // `ref`/`ref mut` overrides the binding mode on edition <= 2021 self.add_rust_2024_migration_desugared_pat( pat_info.top_info.hir_id, pat, ident.span, - def_br_mutbl, ); } user_bind_annot @@ -2380,7 +2378,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_info.top_info.hir_id, pat, inner.span, - inh_mut, ) } } @@ -2772,7 +2769,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_id: HirId, subpat: &'tcx Pat<'tcx>, cutoff_span: Span, - def_br_mutbl: Mutability, ) { // Try to trim the span we're labeling to just the `&` or binding mode that's an issue. // If the subpattern's span is is from an expansion, the emitted label will not be trimmed. @@ -2788,8 +2784,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut table = typeck_results.rust_2024_migration_desugared_pats_mut(); let info = table.entry(pat_id).or_default(); - info.primary_spans.push(trimmed_span); - // Only provide a detailed label if the problematic subpattern isn't from an expansion. // In the case that it's from a macro, we'll add a more detailed note in the emitter. let from_expansion = subpat.span.from_expansion(); @@ -2807,15 +2801,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "this reference pattern" } }; - info.span_labels.push((trimmed_span, primary_label.to_owned())); - - if !from_expansion { - // Add a secondary label covering the whole pattern noting the default binding mode - let def_br_desc = match def_br_mutbl { - Mutability::Not => "default binding mode is `ref`", - Mutability::Mut => "default binding mode is `ref mut`", - }; - info.span_labels.push((subpat.span, def_br_desc.to_owned())); - } + info.primary_labels.push((trimmed_span, primary_label.to_owned())); } } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index a75a7fcd5695..c09418c0ef15 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -816,10 +816,8 @@ impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> { /// emitted during THIR construction. #[derive(TyEncodable, TyDecodable, Debug, HashStable, Default)] pub struct Rust2024IncompatiblePatInfo { - /// Spans for `&`s, `&mut`s, and binding modifiers incompatible with Rust 2024. - pub primary_spans: Vec, - /// Labels for the primary spans and their patterns, to provide additional context. - pub span_labels: Vec<(Span, String)>, + /// Labeled spans for `&`s, `&mut`s, and binding modifiers incompatible with Rust 2024. + pub primary_labels: Vec<(Span, String)>, /// Whether any binding modifiers occur under a non-`move` default binding mode. pub bad_modifiers: bool, /// Whether any `&` or `&mut` patterns occur under a non-`move` default binding mode. diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 0289a6c4073a..e37fe8267842 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, @@ -1109,6 +1110,11 @@ pub(crate) struct Rust2024IncompatiblePatSugg { pub(crate) suggestion: Vec<(Span, String)>, pub(crate) ref_pattern_count: usize, pub(crate) binding_mode_count: usize, + /// Internal state: the ref-mutability of the default binding mode at the subpattern being + /// lowered, with the span where it was introduced. `None` for a by-value default mode. + pub(crate) default_mode_span: Option<(Span, ty::Mutability)>, + /// Labels for where incompatibility-causing by-ref default binding modes were introduced. + pub(crate) default_mode_labels: FxIndexMap, } impl Subdiagnostic for Rust2024IncompatiblePatSugg { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index cdabd283150d..5edaa748f6a7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -53,16 +53,29 @@ pub(super) fn pat_from_hir<'a, 'tcx>( suggestion: Vec::new(), ref_pattern_count: 0, binding_mode_count: 0, + default_mode_span: None, + default_mode_labels: Default::default(), })), }; let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); if let Some(info) = migration_info { let sugg = pcx.rust_2024_migration_suggestion.expect("suggestion should be present"); - let mut spans = MultiSpan::from_spans(info.primary_spans.clone()); - for (span, label) in &info.span_labels { + let mut spans = + MultiSpan::from_spans(info.primary_labels.iter().map(|(span, _)| *span).collect()); + for (span, label) in &info.primary_labels { spans.push_span_label(*span, label.clone()); } + for (span, label_mutbl) in &sugg.default_mode_labels { + // Don't point to a macro call site. + if !span.from_expansion() { + let label = match label_mutbl { + Mutability::Not => "default binding mode is `ref`", + Mutability::Mut => "default binding mode is `ref mut`", + }; + spans.push_span_label(*span, label.to_owned()) + } + } // If a relevant span is from at least edition 2024, this is a hard error. let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024()); if is_hard_error { @@ -96,6 +109,40 @@ pub(super) fn pat_from_hir<'a, 'tcx>( impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { + let adjustments: &[Ty<'tcx>] = + self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); + + let mut opt_old_mode_span = None; + if let Some(s) = &mut self.rust_2024_migration_suggestion + && !adjustments.is_empty() + { + let mut min_mutbl = Mutability::Mut; + let suggestion_str: String = adjustments + .iter() + .map(|ref_ty| { + let &ty::Ref(_, _, mutbl) = ref_ty.kind() else { + span_bug!(pat.span, "pattern implicitly dereferences a non-ref type"); + }; + + match mutbl { + Mutability::Not => { + min_mutbl = Mutability::Not; + "&" + } + Mutability::Mut => "&mut ", + } + }) + .collect(); + s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str)); + s.ref_pattern_count += adjustments.len(); + + // Remember if this changed the default binding mode, in case we want to label it. + if s.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) { + opt_old_mode_span = Some(s.default_mode_span); + s.default_mode_span = Some((pat.span, min_mutbl)); + } + }; + // When implicit dereferences have been inserted in this pattern, the unadjusted lowered // pattern has the type that results *after* dereferencing. For example, in this code: // @@ -124,8 +171,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { _ => self.lower_pattern_unadjusted(pat), }; - let adjustments: &[Ty<'tcx>] = - self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, ref_ty| { debug!("{:?}: wrapping pattern with type {:?}", thir_pat, ref_ty); Box::new(Pat { @@ -136,24 +181,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }); if let Some(s) = &mut self.rust_2024_migration_suggestion - && !adjustments.is_empty() + && let Some(old_mode_span) = opt_old_mode_span { - let suggestion_str: String = adjustments - .iter() - .map(|ref_ty| { - let &ty::Ref(_, _, mutbl) = ref_ty.kind() else { - span_bug!(pat.span, "pattern implicitly dereferences a non-ref type"); - }; - - match mutbl { - ty::Mutability::Not => "&", - ty::Mutability::Mut => "&mut ", - } - }) - .collect(); - s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str)); - s.ref_pattern_count += adjustments.len(); - }; + s.default_mode_span = old_mode_span; + } adjusted_pat } @@ -343,7 +374,22 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), mutability } } - hir::PatKind::Ref(subpattern, _) | hir::PatKind::Box(subpattern) => { + hir::PatKind::Ref(subpattern, _) => { + // Track the default binding mode for the Rust 2024 migration suggestion. + let old_mode_span = self.rust_2024_migration_suggestion.as_mut().and_then(|s| { + if let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span { + // If this eats a by-ref default binding mode, label the binding mode. + s.default_mode_labels.insert(default_mode_span, default_ref_mutbl); + } + s.default_mode_span.take() + }); + let subpattern = self.lower_pattern(subpattern); + if let Some(s) = &mut self.rust_2024_migration_suggestion { + s.default_mode_span = old_mode_span; + } + PatKind::Deref { subpattern } + } + hir::PatKind::Box(subpattern) => { PatKind::Deref { subpattern: self.lower_pattern(subpattern) } } @@ -370,19 +416,26 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .get(pat.hir_id) .expect("missing binding mode"); - if let Some(s) = &mut self.rust_2024_migration_suggestion - && explicit_ba.0 == ByRef::No - && let ByRef::Yes(mutbl) = mode.0 - { - let sugg_str = match mutbl { - Mutability::Not => "ref ", - Mutability::Mut => "ref mut ", - }; - s.suggestion.push(( - pat.span.with_lo(ident.span.lo()).shrink_to_lo(), - sugg_str.to_owned(), - )); - s.binding_mode_count += 1; + if let Some(s) = &mut self.rust_2024_migration_suggestion { + if explicit_ba != hir::BindingMode::NONE + && let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span + { + // If this overrides a by-ref default binding mode, label the binding mode. + s.default_mode_labels.insert(default_mode_span, default_ref_mutbl); + } + if explicit_ba.0 == ByRef::No + && let ByRef::Yes(mutbl) = mode.0 + { + let sugg_str = match mutbl { + Mutability::Not => "ref ", + Mutability::Mut => "ref mut ", + }; + s.suggestion.push(( + pat.span.with_lo(ident.span.lo()).shrink_to_lo(), + sugg_str.to_owned(), + )); + s.binding_mode_count += 1; + } } // A ref x pattern is the same node used for x, and as such it has diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr index d4313f915df3..3dbdda335667 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr @@ -14,10 +14,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; - | ^^^^^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | -^^^^^^^--- + | || + | |this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -35,10 +35,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10 | LL | let [ref x] = &[0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | -^^^--- + | || + | |this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -50,10 +50,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10 | LL | let [ref x] = &mut [0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref mut` + | -^^^--- + | || + | |this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -65,10 +65,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 | LL | let [ref mut x] = &mut [0]; - | ^^^^^^^-- - | | - | this binding modifier - | default binding mode is `ref mut` + | -^^^^^^^--- + | || + | |this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr index 8edb6511f230..14e367f7ee07 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr @@ -2,10 +2,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:15:11 | LL | let [&ref x] = &[&0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | --^^^--- + | | | + | | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -17,10 +17,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:20:11 | LL | let [&ref x] = &mut [&0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | --^^^--- + | | | + | | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -32,10 +32,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:25:15 | LL | let [&mut ref x] = &mut [&mut 0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref mut` + | ------^^^--- + | | | + | | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -47,10 +47,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:30:15 | LL | let [&mut ref mut x] = &mut [&mut 0]; - | ^^^^^^^-- - | | - | this binding modifier - | default binding mode is `ref mut` + | ------^^^^^^^--- + | | | + | | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -62,10 +62,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:39:11 | LL | let [&ref x] = &[&mut 0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | --^^^--- + | | | + | | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -77,10 +77,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:45:11 | LL | let [&ref x] = &mut [&mut 0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | --^^^--- + | | | + | | this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -92,10 +92,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:54:15 | LL | let [&mut ref x] = &[&mut 0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | ------^^^--- + | | | + | | this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -107,10 +107,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; - | ^^^^^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | -^^^^^^^--- + | || + | |this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -128,10 +128,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10 | LL | let [ref x] = &[0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | -^^^--- + | || + | |this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -143,10 +143,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10 | LL | let [ref x] = &mut [0]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref mut` + | -^^^--- + | || + | |this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -158,10 +158,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 | LL | let [ref mut x] = &mut [0]; - | ^^^^^^^-- - | | - | this binding modifier - | default binding mode is `ref mut` + | -^^^^^^^--- + | || + | |this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index cbb94a52878e..febf10cd1f35 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -2,10 +2,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:25:13 | LL | let Foo(mut x) = &Foo(0); - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | ----^^^--- + | | | + | | this binding modifier + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -23,10 +23,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:30:13 | LL | let Foo(mut x) = &mut Foo(0); - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref mut` + | ----^^^--- + | | | + | | this binding modifier + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -39,10 +39,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:35:13 | LL | let Foo(ref x) = &Foo(0); - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | ----^^^--- + | | | + | | this binding modifier + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -55,10 +55,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:40:13 | LL | let Foo(ref x) = &mut Foo(0); - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref mut` + | ----^^^--- + | | | + | | this binding modifier + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -71,10 +71,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:57:13 | LL | let Foo(&x) = &Foo(&0); - | ^- - | | - | this reference pattern - | default binding mode is `ref` + | ----^-- + | | | + | | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -87,10 +87,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:62:13 | LL | let Foo(&mut x) = &Foo(&mut 0); - | ^^^^-- - | | - | this reference pattern - | default binding mode is `ref` + | ----^^^^--- + | | | + | | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -103,10 +103,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:67:13 | LL | let Foo(&x) = &mut Foo(&0); - | ^- - | | - | this reference pattern - | default binding mode is `ref mut` + | ----^-- + | | | + | | this reference pattern + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -119,10 +119,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:72:13 | LL | let Foo(&mut x) = &mut Foo(&mut 0); - | ^^^^-- - | | - | this reference pattern - | default binding mode is `ref mut` + | ----^^^^--- + | | | + | | this reference pattern + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -135,10 +135,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:81:17 | LL | if let Some(&x) = &&&&&Some(&0u8) { - | ^- - | | - | this reference pattern - | default binding mode is `ref` + | -----^-- + | | | + | | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -151,10 +151,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:87:17 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { - | ^^^^-- - | | - | this reference pattern - | default binding mode is `ref` + | -----^^^^--- + | | | + | | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -167,10 +167,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:93:17 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { - | ^- - | | - | this reference pattern - | default binding mode is `ref` + | -----^-- + | | | + | | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -183,10 +183,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:99:17 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - | ^^^^-------------- - | | - | this reference pattern - | default binding mode is `ref mut` + | -----^^^^--------------- + | | | + | | this reference pattern + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -199,10 +199,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:111:21 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | ------------^^^------- + | | | + | | this binding modifier + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -215,12 +215,11 @@ error: binding modifiers and reference patterns may only be written when the def --> $DIR/migration_lint.rs:117:21 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - | ^- ^^^-- - | | | - | | this binding modifier - | | default binding mode is `ref` - | this reference pattern - | default binding mode is `ref` + | ------------^------^^^---- + | | | | + | | | this binding modifier + | | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -233,12 +232,11 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:124:24 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - | ^------- ^- - | | | - | | this reference pattern - | | default binding mode is `ref` - | this reference pattern - | default binding mode is `ref` + | ------------^-----------------^---------------- + | | | | + | | | this reference pattern + | | this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -251,10 +249,11 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:137:15 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - | ^^^-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion - | | - | this binding modifier - | default binding mode is `ref` + | ------^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | | | + | | | occurs within macro expansion + | | this binding modifier + | default binding mode is `ref` | = note: for more information, see = note: this error originates in the macro `migration_lint_macros::mixed_edition_pat` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -267,12 +266,12 @@ error: binding modifiers and reference patterns may only be written when the def --> $DIR/migration_lint.rs:145:10 | LL | let [&mut [ref a]] = &mut [&mut &[0]]; - | ^^^^--^^^--- - | | | - | | this binding modifier - | | default binding mode is `ref` - | this reference pattern - | default binding mode is `ref mut` + | -^^^^--^^^---- + | || || + | || |this binding modifier + | || default binding mode is `ref` + | |this reference pattern + | default binding mode is `ref mut` | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -285,10 +284,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:150:10 | LL | let [&(_)] = &[&0]; - | ^^-- - | | - | this reference pattern - | default binding mode is `ref` + | -^^--- + | || + | |this reference pattern + | default binding mode is `ref` | = warning: this changes meaning in Rust 2024 = note: for more information, see diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index ce93199b1864..ca1749074c19 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -103,10 +103,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:24:20 | LL | test_pat_on_type![(&x,): &(&T,)]; - | ^- - | | - | this reference pattern - | default binding mode is `ref` + | -^--- + | || + | |this reference pattern + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -118,10 +118,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:27:20 | LL | test_pat_on_type![(&mut x,): &(&mut T,)]; - | ^^^^-- - | | - | this reference pattern - | default binding mode is `ref` + | -^^^^---- + | || + | |this reference pattern + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -133,10 +133,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:31:28 | LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; - | ^---- - | | - | this reference pattern - | default binding mode is `ref` + | ---------^------ + | | | + | | this reference pattern + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -148,10 +148,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/min_match_ergonomics_fail.rs:32:20 | LL | test_pat_on_type![(mut x,): &(T,)]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | -^^^---- + | || + | |this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -163,10 +163,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/min_match_ergonomics_fail.rs:33:20 | LL | test_pat_on_type![(ref x,): &(T,)]; - | ^^^-- - | | - | this binding modifier - | default binding mode is `ref` + | -^^^---- + | || + | |this binding modifier + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit @@ -178,10 +178,10 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/min_match_ergonomics_fail.rs:34:20 | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; - | ^^^^^^^-- - | | - | this binding modifier - | default binding mode is `ref mut` + | -^^^^^^^---- + | || + | |this binding modifier + | default binding mode is `ref mut` | = note: for more information, see help: make the implied reference pattern explicit @@ -193,10 +193,10 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:43:10 | LL | (&x,) => x, - | ^- - | | - | this reference pattern - | default binding mode is `ref` + | -^--- + | || + | |this reference pattern + | default binding mode is `ref` | = note: for more information, see help: make the implied reference pattern explicit From a064e786633ac81c35abcf00abd9dc57a40ad9bf Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 4 Feb 2025 03:27:59 -0800 Subject: [PATCH 07/13] don't include trailing open parens in labels for reference patterns --- compiler/rustc_hir_typeck/src/pat.rs | 2 +- .../rfc-3627-match-ergonomics-2024/migration_lint.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 672e81a4c2aa..d0b7c09507fd 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2774,7 +2774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the subpattern's span is is from an expansion, the emitted label will not be trimmed. let source_map = self.tcx.sess.source_map(); let cutoff_span = source_map - .span_extend_prev_while(cutoff_span, char::is_whitespace) + .span_extend_prev_while(cutoff_span, |c| c.is_whitespace() || c == '(') .unwrap_or(cutoff_span); // Ensure we use the syntax context and thus edition of `subpat.span`; this will be a hard // error if the subpattern is of edition >= 2024. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index febf10cd1f35..eaba337f06bb 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -284,7 +284,7 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:150:10 | LL | let [&(_)] = &[&0]; - | -^^--- + | -^---- | || | |this reference pattern | default binding mode is `ref` From 767f82039c221fa609f752d2a2ea4ffd664f8138 Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 5 Feb 2025 01:12:40 -0800 Subject: [PATCH 08/13] separate labels for default binding mode spans into their own notes --- compiler/rustc_hir_typeck/src/pat.rs | 25 ++- compiler/rustc_mir_build/src/errors.rs | 21 ++ .../rustc_mir_build/src/thir/pattern/mod.rs | 10 - ...nding-on-inh-ref-errors.classic2024.stderr | 40 ++-- ...ng-on-inh-ref-errors.structural2024.stderr | 110 ++++++---- .../migration_lint.stderr | 198 +++++++++++------- .../min_match_ergonomics_fail.stderr | 70 ++++--- 7 files changed, 291 insertions(+), 183 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index d0b7c09507fd..0c20a98059c4 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -804,7 +804,7 @@ 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(_)) => { + BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(def_br_mutbl) = def_br => { // 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() @@ -828,18 +828,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_info.top_info.hir_id, pat, ident.span, + def_br_mutbl, ); BindingMode(ByRef::No, Mutability::Mut) } } BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl), BindingMode(ByRef::Yes(_), _) => { - if matches!(def_br, ByRef::Yes(_)) { + if let ByRef::Yes(def_br_mutbl) = def_br { // `ref`/`ref mut` overrides the binding mode on edition <= 2021 self.add_rust_2024_migration_desugared_pat( pat_info.top_info.hir_id, pat, ident.span, + def_br_mutbl, ); } user_bind_annot @@ -2378,6 +2380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_info.top_info.hir_id, pat, inner.span, + inh_mut, ) } } @@ -2769,6 +2772,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_id: HirId, subpat: &'tcx Pat<'tcx>, cutoff_span: Span, + def_br_mutbl: Mutability, ) { // Try to trim the span we're labeling to just the `&` or binding mode that's an issue. // If the subpattern's span is is from an expansion, the emitted label will not be trimmed. @@ -2791,16 +2795,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // NB: This wording assumes the only expansions that can produce problematic reference // patterns and bindings are macros. If a desugaring or AST pass is added that can do // so, we may want to inspect the span's source callee or macro backtrace. - "occurs within macro expansion" + "occurs within macro expansion".to_owned() } else { - if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) { + let pat_kind = if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) { info.bad_modifiers |= true; - "this binding modifier" + "binding modifier" } else { info.bad_ref_pats |= true; - "this reference pattern" - } + "reference pattern" + }; + let dbm_str = match def_br_mutbl { + Mutability::Not => "ref", + Mutability::Mut => "ref mut", + }; + format!("{pat_kind} not allowed under `{dbm_str}` default binding mode") }; - info.primary_labels.push((trimmed_span, primary_label.to_owned())); + info.primary_labels.push((trimmed_span, primary_label)); } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index e37fe8267842..e83901e175d1 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1123,6 +1123,27 @@ impl Subdiagnostic for Rust2024IncompatiblePatSugg { diag: &mut Diag<'_, G>, _f: &F, ) { + // Format and emit explanatory notes about default binding modes. Reversing the spans' order + // means if we have nested spans, the innermost ones will be visited first. + for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() { + // Don't point to a macro call site. + if !span.from_expansion() { + let dbm_str = match def_br_mutbl { + ty::Mutability::Not => "ref", + ty::Mutability::Mut => "ref mut", + }; + let note_msg = format!( + "the default binding mode changed to `{dbm_str}` because this has type `{}_`", + def_br_mutbl.ref_prefix_str() + ); + let label_msg = format!("the default binding mode is `{dbm_str}`, introduced here"); + let mut label = MultiSpan::from(span); + label.push_span_label(span, label_msg); + diag.span_note(label, note_msg); + } + } + + // Format and emit the suggestion. let applicability = if self.suggestion.iter().all(|(span, _)| span.can_be_used_for_suggestions()) { Applicability::MachineApplicable diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 5edaa748f6a7..f72ce2fe6fbf 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -66,16 +66,6 @@ pub(super) fn pat_from_hir<'a, 'tcx>( for (span, label) in &info.primary_labels { spans.push_span_label(*span, label.clone()); } - for (span, label_mutbl) in &sugg.default_mode_labels { - // Don't point to a macro call site. - if !span.from_expansion() { - let label = match label_mutbl { - Mutability::Not => "default binding mode is `ref`", - Mutability::Mut => "default binding mode is `ref mut`", - }; - spans.push_span_label(*span, label.to_owned()) - } - } // If a relevant span is from at least edition 2024, this is a hard error. let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024()); if is_hard_error { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr index 3dbdda335667..74e164619fa9 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr @@ -14,12 +14,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; - | -^^^^^^^--- - | || - | |this binding modifier - | default binding mode is `ref` + | ^^^^^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/ref-binding-on-inh-ref-errors.rs:67:9 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &[ref mut x] = &[0]; @@ -35,12 +37,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10 | LL | let [ref x] = &[0]; - | -^^^--- - | || - | |this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/ref-binding-on-inh-ref-errors.rs:75:9 + | +LL | let [ref x] = &[0]; + | ^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &[ref x] = &[0]; @@ -50,12 +54,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10 | LL | let [ref x] = &mut [0]; - | -^^^--- - | || - | |this binding modifier - | default binding mode is `ref mut` + | ^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9 + | +LL | let [ref x] = &mut [0]; + | ^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut [ref x] = &mut [0]; @@ -65,12 +71,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 | LL | let [ref mut x] = &mut [0]; - | -^^^^^^^--- - | || - | |this binding modifier - | default binding mode is `ref mut` + | ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9 + | +LL | let [ref mut x] = &mut [0]; + | ^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut [ref mut x] = &mut [0]; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr index 14e367f7ee07..422c169d7fd1 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr @@ -2,12 +2,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:15:11 | LL | let [&ref x] = &[&0]; - | --^^^--- - | | | - | | this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/ref-binding-on-inh-ref-errors.rs:15:9 + | +LL | let [&ref x] = &[&0]; + | ^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &[&ref x] = &[&0]; @@ -17,12 +19,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:20:11 | LL | let [&ref x] = &mut [&0]; - | --^^^--- - | | | - | | this binding modifier - | default binding mode is `ref mut` + | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/ref-binding-on-inh-ref-errors.rs:20:9 + | +LL | let [&ref x] = &mut [&0]; + | ^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut [&ref x] = &mut [&0]; @@ -32,12 +36,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:25:15 | LL | let [&mut ref x] = &mut [&mut 0]; - | ------^^^--- - | | | - | | this binding modifier - | default binding mode is `ref mut` + | ^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/ref-binding-on-inh-ref-errors.rs:25:9 + | +LL | let [&mut ref x] = &mut [&mut 0]; + | ^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut [&mut ref x] = &mut [&mut 0]; @@ -47,12 +53,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:30:15 | LL | let [&mut ref mut x] = &mut [&mut 0]; - | ------^^^^^^^--- - | | | - | | this binding modifier - | default binding mode is `ref mut` + | ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/ref-binding-on-inh-ref-errors.rs:30:9 + | +LL | let [&mut ref mut x] = &mut [&mut 0]; + | ^^^^^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut [&mut ref mut x] = &mut [&mut 0]; @@ -62,12 +70,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:39:11 | LL | let [&ref x] = &[&mut 0]; - | --^^^--- - | | | - | | this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/ref-binding-on-inh-ref-errors.rs:39:9 + | +LL | let [&ref x] = &[&mut 0]; + | ^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &[&ref x] = &[&mut 0]; @@ -77,12 +87,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:45:11 | LL | let [&ref x] = &mut [&mut 0]; - | --^^^--- - | | | - | | this binding modifier - | default binding mode is `ref mut` + | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/ref-binding-on-inh-ref-errors.rs:45:9 + | +LL | let [&ref x] = &mut [&mut 0]; + | ^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut [&ref x] = &mut [&mut 0]; @@ -92,12 +104,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:54:15 | LL | let [&mut ref x] = &[&mut 0]; - | ------^^^--- - | | | - | | this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/ref-binding-on-inh-ref-errors.rs:54:9 + | +LL | let [&mut ref x] = &[&mut 0]; + | ^^^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &[&mut ref x] = &[&mut 0]; @@ -107,12 +121,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10 | LL | let [ref mut x] = &[0]; - | -^^^^^^^--- - | || - | |this binding modifier - | default binding mode is `ref` + | ^^^^^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/ref-binding-on-inh-ref-errors.rs:67:9 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &[ref mut x] = &[0]; @@ -128,12 +144,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10 | LL | let [ref x] = &[0]; - | -^^^--- - | || - | |this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/ref-binding-on-inh-ref-errors.rs:75:9 + | +LL | let [ref x] = &[0]; + | ^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &[ref x] = &[0]; @@ -143,12 +161,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10 | LL | let [ref x] = &mut [0]; - | -^^^--- - | || - | |this binding modifier - | default binding mode is `ref mut` + | ^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9 + | +LL | let [ref x] = &mut [0]; + | ^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut [ref x] = &mut [0]; @@ -158,12 +178,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 | LL | let [ref mut x] = &mut [0]; - | -^^^^^^^--- - | || - | |this binding modifier - | default binding mode is `ref mut` + | ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9 + | +LL | let [ref mut x] = &mut [0]; + | ^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut [ref mut x] = &mut [0]; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index eaba337f06bb..cfbd260e0e9a 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -2,13 +2,15 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:25:13 | LL | let Foo(mut x) = &Foo(0); - | ----^^^--- - | | | - | | this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:25:9 + | +LL | let Foo(mut x) = &Foo(0); + | ^^^^^^^^^^ the default binding mode is `ref`, introduced here note: the lint level is defined here --> $DIR/migration_lint.rs:7:9 | @@ -23,13 +25,15 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:30:13 | LL | let Foo(mut x) = &mut Foo(0); - | ----^^^--- - | | | - | | this binding modifier - | default binding mode is `ref mut` + | ^^^ binding modifier not allowed under `ref mut` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/migration_lint.rs:30:9 + | +LL | let Foo(mut x) = &mut Foo(0); + | ^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut Foo(mut x) = &mut Foo(0); @@ -39,13 +43,15 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:35:13 | LL | let Foo(ref x) = &Foo(0); - | ----^^^--- - | | | - | | this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:35:9 + | +LL | let Foo(ref x) = &Foo(0); + | ^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &Foo(ref x) = &Foo(0); @@ -55,13 +61,15 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:40:13 | LL | let Foo(ref x) = &mut Foo(0); - | ----^^^--- - | | | - | | this binding modifier - | default binding mode is `ref mut` + | ^^^ binding modifier not allowed under `ref mut` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/migration_lint.rs:40:9 + | +LL | let Foo(ref x) = &mut Foo(0); + | ^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut Foo(ref x) = &mut Foo(0); @@ -71,13 +79,15 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:57:13 | LL | let Foo(&x) = &Foo(&0); - | ----^-- - | | | - | | this reference pattern - | default binding mode is `ref` + | ^ reference pattern not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:57:9 + | +LL | let Foo(&x) = &Foo(&0); + | ^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &Foo(&x) = &Foo(&0); @@ -87,13 +97,15 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:62:13 | LL | let Foo(&mut x) = &Foo(&mut 0); - | ----^^^^--- - | | | - | | this reference pattern - | default binding mode is `ref` + | ^^^^ reference pattern not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:62:9 + | +LL | let Foo(&mut x) = &Foo(&mut 0); + | ^^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &Foo(&mut x) = &Foo(&mut 0); @@ -103,13 +115,15 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:67:13 | LL | let Foo(&x) = &mut Foo(&0); - | ----^-- - | | | - | | this reference pattern - | default binding mode is `ref mut` + | ^ reference pattern not allowed under `ref mut` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/migration_lint.rs:67:9 + | +LL | let Foo(&x) = &mut Foo(&0); + | ^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut Foo(&x) = &mut Foo(&0); @@ -119,13 +133,15 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:72:13 | LL | let Foo(&mut x) = &mut Foo(&mut 0); - | ----^^^^--- - | | | - | | this reference pattern - | default binding mode is `ref mut` + | ^^^^ reference pattern not allowed under `ref mut` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/migration_lint.rs:72:9 + | +LL | let Foo(&mut x) = &mut Foo(&mut 0); + | ^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | let &mut Foo(&mut x) = &mut Foo(&mut 0); @@ -135,13 +151,15 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:81:17 | LL | if let Some(&x) = &&&&&Some(&0u8) { - | -----^-- - | | | - | | this reference pattern - | default binding mode is `ref` + | ^ reference pattern not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:81:12 + | +LL | if let Some(&x) = &&&&&Some(&0u8) { + | ^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference patterns explicit | LL | if let &&&&&Some(&x) = &&&&&Some(&0u8) { @@ -151,13 +169,15 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:87:17 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { - | -----^^^^--- - | | | - | | this reference pattern - | default binding mode is `ref` + | ^^^^ reference pattern not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:87:12 + | +LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { + | ^^^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference patterns explicit | LL | if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { @@ -167,13 +187,15 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:93:17 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { - | -----^-- - | | | - | | this reference pattern - | default binding mode is `ref` + | ^ reference pattern not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:93:12 + | +LL | if let Some(&x) = &&&&&mut Some(&0u8) { + | ^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference patterns explicit | LL | if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { @@ -183,13 +205,15 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:99:17 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - | -----^^^^--------------- - | | | - | | this reference pattern - | default binding mode is `ref mut` + | ^^^^ reference pattern not allowed under `ref mut` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/migration_lint.rs:99:12 + | +LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference patterns and variable binding mode explicit | LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { @@ -199,13 +223,15 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:111:21 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - | ------------^^^------- - | | | - | | this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:111:9 + | +LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern and variable binding modes explicit | LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; @@ -215,14 +241,17 @@ error: binding modifiers and reference patterns may only be written when the def --> $DIR/migration_lint.rs:117:21 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - | ------------^------^^^---- - | | | | - | | | this binding modifier - | | this reference pattern - | default binding mode is `ref` + | ^ ^^^ binding modifier not allowed under `ref` default binding mode + | | + | reference pattern not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:117:9 + | +LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern and variable binding mode explicit | LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; @@ -232,14 +261,17 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:124:24 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - | ------------^-----------------^---------------- - | | | | - | | | this reference pattern - | | this reference pattern - | default binding mode is `ref` + | ^ ^ reference pattern not allowed under `ref` default binding mode + | | + | reference pattern not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:124:12 + | +LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference patterns and variable binding mode explicit | LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = @@ -249,13 +281,16 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/migration_lint.rs:137:15 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - | ------^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | | | - | | | occurs within macro expansion - | | this binding modifier - | default binding mode is `ref` + | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion + | | + | binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:137:9 + | +LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here = note: this error originates in the macro `migration_lint_macros::mixed_edition_pat` (in Nightly builds, run with -Z macro-backtrace for more info) help: make the implied reference pattern explicit | @@ -266,15 +301,22 @@ error: binding modifiers and reference patterns may only be written when the def --> $DIR/migration_lint.rs:145:10 | LL | let [&mut [ref a]] = &mut [&mut &[0]]; - | -^^^^--^^^---- - | || || - | || |this binding modifier - | || default binding mode is `ref` - | |this reference pattern - | default binding mode is `ref mut` + | ^^^^ ^^^ binding modifier not allowed under `ref` default binding mode + | | + | reference pattern not allowed under `ref mut` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:145:15 + | +LL | let [&mut [ref a]] = &mut [&mut &[0]]; + | ^^^^^^^ the default binding mode is `ref`, introduced here +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/migration_lint.rs:145:9 + | +LL | let [&mut [ref a]] = &mut [&mut &[0]]; + | ^^^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference patterns explicit | LL | let &mut [&mut &[ref a]] = &mut [&mut &[0]]; @@ -284,13 +326,15 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/migration_lint.rs:150:10 | LL | let [&(_)] = &[&0]; - | -^---- - | || - | |this reference pattern - | default binding mode is `ref` + | ^ reference pattern not allowed under `ref` default binding mode | = warning: this changes meaning in Rust 2024 = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/migration_lint.rs:150:9 + | +LL | let [&(_)] = &[&0]; + | ^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | let &[&(_)] = &[&0]; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index ca1749074c19..1d13723370e7 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -103,12 +103,14 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:24:20 | LL | test_pat_on_type![(&x,): &(&T,)]; - | -^--- - | || - | |this reference pattern - | default binding mode is `ref` + | ^ reference pattern not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/min_match_ergonomics_fail.rs:24:19 + | +LL | test_pat_on_type![(&x,): &(&T,)]; + | ^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | test_pat_on_type![&(&x,): &(&T,)]; @@ -118,12 +120,14 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:27:20 | LL | test_pat_on_type![(&mut x,): &(&mut T,)]; - | -^^^^---- - | || - | |this reference pattern - | default binding mode is `ref` + | ^^^^ reference pattern not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/min_match_ergonomics_fail.rs:27:19 + | +LL | test_pat_on_type![(&mut x,): &(&mut T,)]; + | ^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | test_pat_on_type![&(&mut x,): &(&mut T,)]; @@ -133,12 +137,14 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:31:28 | LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; - | ---------^------ - | | | - | | this reference pattern - | default binding mode is `ref` + | ^ reference pattern not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/min_match_ergonomics_fail.rs:31:19 + | +LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; + | ^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | test_pat_on_type![&Foo { f: &(x,) }: &Foo]; @@ -148,12 +154,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/min_match_ergonomics_fail.rs:32:20 | LL | test_pat_on_type![(mut x,): &(T,)]; - | -^^^---- - | || - | |this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/min_match_ergonomics_fail.rs:32:19 + | +LL | test_pat_on_type![(mut x,): &(T,)]; + | ^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | test_pat_on_type![&(mut x,): &(T,)]; @@ -163,12 +171,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/min_match_ergonomics_fail.rs:33:20 | LL | test_pat_on_type![(ref x,): &(T,)]; - | -^^^---- - | || - | |this binding modifier - | default binding mode is `ref` + | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/min_match_ergonomics_fail.rs:33:19 + | +LL | test_pat_on_type![(ref x,): &(T,)]; + | ^^^^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | test_pat_on_type![&(ref x,): &(T,)]; @@ -178,12 +188,14 @@ error: binding modifiers may only be written when the default binding mode is `m --> $DIR/min_match_ergonomics_fail.rs:34:20 | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; - | -^^^^^^^---- - | || - | |this binding modifier - | default binding mode is `ref mut` + | ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref mut` because this has type `&mut _` + --> $DIR/min_match_ergonomics_fail.rs:34:19 + | +LL | test_pat_on_type![(ref mut x,): &mut (T,)]; + | ^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here help: make the implied reference pattern explicit | LL | test_pat_on_type![&mut (ref mut x,): &mut (T,)]; @@ -193,12 +205,14 @@ error: reference patterns may only be written when the default binding mode is ` --> $DIR/min_match_ergonomics_fail.rs:43:10 | LL | (&x,) => x, - | -^--- - | || - | |this reference pattern - | default binding mode is `ref` + | ^ reference pattern not allowed under `ref` default binding mode | = note: for more information, see +note: the default binding mode changed to `ref` because this has type `&_` + --> $DIR/min_match_ergonomics_fail.rs:43:9 + | +LL | (&x,) => x, + | ^^^^^ the default binding mode is `ref`, introduced here help: make the implied reference pattern explicit | LL | &(&x,) => x, From a5cc4cbe64876c339cc1fb47fb962792bc142146 Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 5 Feb 2025 09:05:39 -0800 Subject: [PATCH 09/13] reword default binding mode notes --- compiler/rustc_mir_build/src/errors.rs | 12 +-- ...nding-on-inh-ref-errors.classic2024.stderr | 16 ++-- ...ng-on-inh-ref-errors.structural2024.stderr | 44 +++++------ .../migration_lint.stderr | 76 +++++++++---------- .../min_match_ergonomics_fail.stderr | 28 +++---- 5 files changed, 85 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index e83901e175d1..55fd42457b7e 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1128,15 +1128,9 @@ impl Subdiagnostic for Rust2024IncompatiblePatSugg { for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() { // Don't point to a macro call site. if !span.from_expansion() { - let dbm_str = match def_br_mutbl { - ty::Mutability::Not => "ref", - ty::Mutability::Mut => "ref mut", - }; - let note_msg = format!( - "the default binding mode changed to `{dbm_str}` because this has type `{}_`", - def_br_mutbl.ref_prefix_str() - ); - let label_msg = format!("the default binding mode is `{dbm_str}`, introduced here"); + let note_msg = "matching on a reference type with a non-reference pattern changes the default binding mode"; + let label_msg = + format!("this matches on type `{}_`", def_br_mutbl.ref_prefix_str()); let mut label = MultiSpan::from(span); label.push_span_label(span, label_msg); diag.span_note(label, note_msg); diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr index 74e164619fa9..b7fb70dfd246 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr @@ -17,11 +17,11 @@ LL | let [ref mut x] = &[0]; | ^^^^^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:67:9 | LL | let [ref mut x] = &[0]; - | ^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &[ref mut x] = &[0]; @@ -40,11 +40,11 @@ LL | let [ref x] = &[0]; | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:75:9 | LL | let [ref x] = &[0]; - | ^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &[ref x] = &[0]; @@ -57,11 +57,11 @@ LL | let [ref x] = &mut [0]; | ^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9 | LL | let [ref x] = &mut [0]; - | ^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut [ref x] = &mut [0]; @@ -74,11 +74,11 @@ LL | let [ref mut x] = &mut [0]; | ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9 | LL | let [ref mut x] = &mut [0]; - | ^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut [ref mut x] = &mut [0]; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr index 422c169d7fd1..31930e8c0337 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr @@ -5,11 +5,11 @@ LL | let [&ref x] = &[&0]; | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:15:9 | LL | let [&ref x] = &[&0]; - | ^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &[&ref x] = &[&0]; @@ -22,11 +22,11 @@ LL | let [&ref x] = &mut [&0]; | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:20:9 | LL | let [&ref x] = &mut [&0]; - | ^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut [&ref x] = &mut [&0]; @@ -39,11 +39,11 @@ LL | let [&mut ref x] = &mut [&mut 0]; | ^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:25:9 | LL | let [&mut ref x] = &mut [&mut 0]; - | ^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut [&mut ref x] = &mut [&mut 0]; @@ -56,11 +56,11 @@ LL | let [&mut ref mut x] = &mut [&mut 0]; | ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:30:9 | LL | let [&mut ref mut x] = &mut [&mut 0]; - | ^^^^^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut [&mut ref mut x] = &mut [&mut 0]; @@ -73,11 +73,11 @@ LL | let [&ref x] = &[&mut 0]; | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:39:9 | LL | let [&ref x] = &[&mut 0]; - | ^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &[&ref x] = &[&mut 0]; @@ -90,11 +90,11 @@ LL | let [&ref x] = &mut [&mut 0]; | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:45:9 | LL | let [&ref x] = &mut [&mut 0]; - | ^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut [&ref x] = &mut [&mut 0]; @@ -107,11 +107,11 @@ LL | let [&mut ref x] = &[&mut 0]; | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:54:9 | LL | let [&mut ref x] = &[&mut 0]; - | ^^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &[&mut ref x] = &[&mut 0]; @@ -124,11 +124,11 @@ LL | let [ref mut x] = &[0]; | ^^^^^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:67:9 | LL | let [ref mut x] = &[0]; - | ^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &[ref mut x] = &[0]; @@ -147,11 +147,11 @@ LL | let [ref x] = &[0]; | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:75:9 | LL | let [ref x] = &[0]; - | ^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &[ref x] = &[0]; @@ -164,11 +164,11 @@ LL | let [ref x] = &mut [0]; | ^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9 | LL | let [ref x] = &mut [0]; - | ^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut [ref x] = &mut [0]; @@ -181,11 +181,11 @@ LL | let [ref mut x] = &mut [0]; | ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9 | LL | let [ref mut x] = &mut [0]; - | ^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut [ref mut x] = &mut [0]; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index cfbd260e0e9a..ea3283d3a921 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -6,11 +6,11 @@ LL | let Foo(mut x) = &Foo(0); | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:25:9 | LL | let Foo(mut x) = &Foo(0); - | ^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^ this matches on type `&_` note: the lint level is defined here --> $DIR/migration_lint.rs:7:9 | @@ -29,11 +29,11 @@ LL | let Foo(mut x) = &mut Foo(0); | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:30:9 | LL | let Foo(mut x) = &mut Foo(0); - | ^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut Foo(mut x) = &mut Foo(0); @@ -47,11 +47,11 @@ LL | let Foo(ref x) = &Foo(0); | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:35:9 | LL | let Foo(ref x) = &Foo(0); - | ^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &Foo(ref x) = &Foo(0); @@ -65,11 +65,11 @@ LL | let Foo(ref x) = &mut Foo(0); | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:40:9 | LL | let Foo(ref x) = &mut Foo(0); - | ^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut Foo(ref x) = &mut Foo(0); @@ -83,11 +83,11 @@ LL | let Foo(&x) = &Foo(&0); | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:57:9 | LL | let Foo(&x) = &Foo(&0); - | ^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &Foo(&x) = &Foo(&0); @@ -101,11 +101,11 @@ LL | let Foo(&mut x) = &Foo(&mut 0); | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:62:9 | LL | let Foo(&mut x) = &Foo(&mut 0); - | ^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &Foo(&mut x) = &Foo(&mut 0); @@ -119,11 +119,11 @@ LL | let Foo(&x) = &mut Foo(&0); | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:67:9 | LL | let Foo(&x) = &mut Foo(&0); - | ^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut Foo(&x) = &mut Foo(&0); @@ -137,11 +137,11 @@ LL | let Foo(&mut x) = &mut Foo(&mut 0); | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:72:9 | LL | let Foo(&mut x) = &mut Foo(&mut 0); - | ^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | let &mut Foo(&mut x) = &mut Foo(&mut 0); @@ -155,11 +155,11 @@ LL | if let Some(&x) = &&&&&Some(&0u8) { | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:81:12 | LL | if let Some(&x) = &&&&&Some(&0u8) { - | ^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^ this matches on type `&_` help: make the implied reference patterns explicit | LL | if let &&&&&Some(&x) = &&&&&Some(&0u8) { @@ -173,11 +173,11 @@ LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:87:12 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { - | ^^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^^ this matches on type `&_` help: make the implied reference patterns explicit | LL | if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { @@ -191,11 +191,11 @@ LL | if let Some(&x) = &&&&&mut Some(&0u8) { | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:93:12 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { - | ^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^ this matches on type `&_` help: make the implied reference patterns explicit | LL | if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { @@ -209,11 +209,11 @@ LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:99:12 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference patterns and variable binding mode explicit | LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { @@ -227,11 +227,11 @@ LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:111:9 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_` help: make the implied reference pattern and variable binding modes explicit | LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; @@ -247,11 +247,11 @@ LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:117:9 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_` help: make the implied reference pattern and variable binding mode explicit | LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; @@ -267,11 +267,11 @@ LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:124:12 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_` help: make the implied reference patterns and variable binding mode explicit | LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = @@ -286,11 +286,11 @@ LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { | binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:137:9 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_` = note: this error originates in the macro `migration_lint_macros::mixed_edition_pat` (in Nightly builds, run with -Z macro-backtrace for more info) help: make the implied reference pattern explicit | @@ -307,16 +307,16 @@ LL | let [&mut [ref a]] = &mut [&mut &[0]]; | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:145:15 | LL | let [&mut [ref a]] = &mut [&mut &[0]]; - | ^^^^^^^ the default binding mode is `ref`, introduced here -note: the default binding mode changed to `ref mut` because this has type `&mut _` + | ^^^^^^^ this matches on type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:145:9 | LL | let [&mut [ref a]] = &mut [&mut &[0]]; - | ^^^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference patterns explicit | LL | let &mut [&mut &[ref a]] = &mut [&mut &[0]]; @@ -330,11 +330,11 @@ LL | let [&(_)] = &[&0]; | = warning: this changes meaning in Rust 2024 = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/migration_lint.rs:150:9 | LL | let [&(_)] = &[&0]; - | ^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | let &[&(_)] = &[&0]; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index 1d13723370e7..aaa448ea334f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -106,11 +106,11 @@ LL | test_pat_on_type![(&x,): &(&T,)]; | ^ reference pattern not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/min_match_ergonomics_fail.rs:24:19 | LL | test_pat_on_type![(&x,): &(&T,)]; - | ^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | test_pat_on_type![&(&x,): &(&T,)]; @@ -123,11 +123,11 @@ LL | test_pat_on_type![(&mut x,): &(&mut T,)]; | ^^^^ reference pattern not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/min_match_ergonomics_fail.rs:27:19 | LL | test_pat_on_type![(&mut x,): &(&mut T,)]; - | ^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | test_pat_on_type![&(&mut x,): &(&mut T,)]; @@ -140,11 +140,11 @@ LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; | ^ reference pattern not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/min_match_ergonomics_fail.rs:31:19 | LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; - | ^^^^^^^^^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | test_pat_on_type![&Foo { f: &(x,) }: &Foo]; @@ -157,11 +157,11 @@ LL | test_pat_on_type![(mut x,): &(T,)]; | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/min_match_ergonomics_fail.rs:32:19 | LL | test_pat_on_type![(mut x,): &(T,)]; - | ^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | test_pat_on_type![&(mut x,): &(T,)]; @@ -174,11 +174,11 @@ LL | test_pat_on_type![(ref x,): &(T,)]; | ^^^ binding modifier not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/min_match_ergonomics_fail.rs:33:19 | LL | test_pat_on_type![(ref x,): &(T,)]; - | ^^^^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | test_pat_on_type![&(ref x,): &(T,)]; @@ -191,11 +191,11 @@ LL | test_pat_on_type![(ref mut x,): &mut (T,)]; | ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref mut` because this has type `&mut _` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/min_match_ergonomics_fail.rs:34:19 | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; - | ^^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here + | ^^^^^^^^^^^^ this matches on type `&mut _` help: make the implied reference pattern explicit | LL | test_pat_on_type![&mut (ref mut x,): &mut (T,)]; @@ -208,11 +208,11 @@ LL | (&x,) => x, | ^ reference pattern not allowed under `ref` default binding mode | = note: for more information, see -note: the default binding mode changed to `ref` because this has type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode --> $DIR/min_match_ergonomics_fail.rs:43:9 | LL | (&x,) => x, - | ^^^^^ the default binding mode is `ref`, introduced here + | ^^^^^ this matches on type `&_` help: make the implied reference pattern explicit | LL | &(&x,) => x, From 060cc37f3225dd69b5d0df089eec52ff92953b01 Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 5 Feb 2025 09:09:42 -0800 Subject: [PATCH 10/13] peace of mind: remove a call to `Option::expect` --- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index f72ce2fe6fbf..d4a3d1516c89 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -59,8 +59,9 @@ pub(super) fn pat_from_hir<'a, 'tcx>( }; let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); - if let Some(info) = migration_info { - let sugg = pcx.rust_2024_migration_suggestion.expect("suggestion should be present"); + if let Some(info) = migration_info + && let Some(sugg) = pcx.rust_2024_migration_suggestion + { let mut spans = MultiSpan::from_spans(info.primary_labels.iter().map(|(span, _)| *span).collect()); for (span, label) in &info.primary_labels { From b32a5331dcdcc1993fefeff412a20766557e558d Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 5 Feb 2025 04:05:01 -0800 Subject: [PATCH 11/13] try to suggest eliding redundant binding modifiers --- compiler/rustc_hir_typeck/src/pat.rs | 23 +++++++- .../rustc_middle/src/ty/typeck_results.rs | 4 +- compiler/rustc_mir_build/src/errors.rs | 23 +++++--- .../rustc_mir_build/src/thir/pattern/mod.rs | 58 ++++++++++--------- .../migration_lint.fixed | 2 +- .../migration_lint.stderr | 7 ++- .../min_match_ergonomics_fail.stderr | 14 +++-- 7 files changed, 82 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 0c20a98059c4..080a519023ce 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2786,7 +2786,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut typeck_results = self.typeck_results.borrow_mut(); let mut table = typeck_results.rust_2024_migration_desugared_pats_mut(); - let info = table.entry(pat_id).or_default(); + // FIXME(ref_pat_eat_one_layer_2024): The migration diagnostic doesn't know how to track the + // default binding mode in the presence of Rule 3 or Rule 5. As a consequence, the labels it + // gives for default binding modes are wrong, as well as suggestions based on the default + // binding mode. This keeps it from making those suggestions, as doing so could panic. + let info = table.entry(pat_id).or_insert_with(|| ty::Rust2024IncompatiblePatInfo { + primary_labels: Vec::new(), + bad_modifiers: false, + bad_ref_pats: false, + suggest_eliding_modes: !self.tcx.features().ref_pat_eat_one_layer_2024() + && !self.tcx.features().ref_pat_eat_one_layer_2024_structural(), + }); // Only provide a detailed label if the problematic subpattern isn't from an expansion. // In the case that it's from a macro, we'll add a more detailed note in the emitter. @@ -2797,11 +2807,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // so, we may want to inspect the span's source callee or macro backtrace. "occurs within macro expansion".to_owned() } else { - let pat_kind = if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) { + let pat_kind = if let PatKind::Binding(user_bind_annot, _, _, _) = subpat.kind { info.bad_modifiers |= true; + // If the user-provided binding modifier doesn't match the default binding mode, we'll + // need to suggest reference patterns, which can affect other bindings. + // For simplicity, we opt to suggest making the pattern fully explicit. + info.suggest_eliding_modes &= + user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not); "binding modifier" } else { info.bad_ref_pats |= true; + // For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll + // suggest adding them instead, which can affect the types assigned to bindings. + // As such, we opt to suggest making the pattern fully explicit. + info.suggest_eliding_modes = false; "reference pattern" }; let dbm_str = match def_br_mutbl { diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index c09418c0ef15..df3413352089 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -814,7 +814,7 @@ impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> { /// Information on a pattern incompatible with Rust 2024, for use by the error/migration diagnostic /// emitted during THIR construction. -#[derive(TyEncodable, TyDecodable, Debug, HashStable, Default)] +#[derive(TyEncodable, TyDecodable, Debug, HashStable)] pub struct Rust2024IncompatiblePatInfo { /// Labeled spans for `&`s, `&mut`s, and binding modifiers incompatible with Rust 2024. pub primary_labels: Vec<(Span, String)>, @@ -822,4 +822,6 @@ pub struct Rust2024IncompatiblePatInfo { pub bad_modifiers: bool, /// Whether any `&` or `&mut` patterns occur under a non-`move` default binding mode. pub bad_ref_pats: bool, + /// If `true`, we can give a simpler suggestion solely by eliding explicit binding modifiers. + pub suggest_eliding_modes: bool, } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 55fd42457b7e..3707685b3add 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1107,6 +1107,9 @@ pub(crate) struct Rust2024IncompatiblePat { } pub(crate) struct Rust2024IncompatiblePatSugg { + /// If true, our suggestion is to elide explicit binding modifiers. + /// If false, our suggestion is to make the pattern fully explicit. + pub(crate) suggest_eliding_modes: bool, pub(crate) suggestion: Vec<(Span, String)>, pub(crate) ref_pattern_count: usize, pub(crate) binding_mode_count: usize, @@ -1144,16 +1147,18 @@ impl Subdiagnostic for Rust2024IncompatiblePatSugg { } else { Applicability::MaybeIncorrect }; - let plural_derefs = pluralize!(self.ref_pattern_count); - let and_modes = if self.binding_mode_count > 0 { - format!(" and variable binding mode{}", pluralize!(self.binding_mode_count)) + let msg = if self.suggest_eliding_modes { + let plural_modes = pluralize!(self.binding_mode_count); + format!("remove the unnecessary binding modifier{plural_modes}") } else { - String::new() + let plural_derefs = pluralize!(self.ref_pattern_count); + let and_modes = if self.binding_mode_count > 0 { + format!(" and variable binding mode{}", pluralize!(self.binding_mode_count)) + } else { + String::new() + }; + format!("make the implied reference pattern{plural_derefs}{and_modes} explicit") }; - diag.multipart_suggestion_verbose( - format!("make the implied reference pattern{plural_derefs}{and_modes} explicit"), - self.suggestion, - applicability, - ); + diag.multipart_suggestion_verbose(msg, self.suggestion, applicability); } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d4a3d1516c89..dde571f671a4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -49,13 +49,16 @@ pub(super) fn pat_from_hir<'a, 'tcx>( tcx, typing_env, typeck_results, - rust_2024_migration_suggestion: migration_info.and(Some(Rust2024IncompatiblePatSugg { - suggestion: Vec::new(), - ref_pattern_count: 0, - binding_mode_count: 0, - default_mode_span: None, - default_mode_labels: Default::default(), - })), + rust_2024_migration_suggestion: migration_info.and_then(|info| { + Some(Rust2024IncompatiblePatSugg { + suggest_eliding_modes: info.suggest_eliding_modes, + suggestion: Vec::new(), + ref_pattern_count: 0, + binding_mode_count: 0, + default_mode_span: None, + default_mode_labels: Default::default(), + }) + }), }; let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); @@ -107,27 +110,22 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Some(s) = &mut self.rust_2024_migration_suggestion && !adjustments.is_empty() { - let mut min_mutbl = Mutability::Mut; - let suggestion_str: String = adjustments - .iter() - .map(|ref_ty| { - let &ty::Ref(_, _, mutbl) = ref_ty.kind() else { - span_bug!(pat.span, "pattern implicitly dereferences a non-ref type"); - }; - - match mutbl { - Mutability::Not => { - min_mutbl = Mutability::Not; - "&" - } - Mutability::Mut => "&mut ", - } - }) - .collect(); - s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str)); - s.ref_pattern_count += adjustments.len(); + let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| { + let &ty::Ref(_, _, mutbl) = ref_ty.kind() else { + span_bug!(pat.span, "pattern implicitly dereferences a non-ref type"); + }; + mutbl + }); + + if !s.suggest_eliding_modes { + let suggestion_str: String = + implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect(); + s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str)); + s.ref_pattern_count += adjustments.len(); + } // Remember if this changed the default binding mode, in case we want to label it. + let min_mutbl = implicit_deref_mutbls.min().unwrap(); if s.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) { opt_old_mode_span = Some(s.default_mode_span); s.default_mode_span = Some((pat.span, min_mutbl)); @@ -413,8 +411,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { { // If this overrides a by-ref default binding mode, label the binding mode. s.default_mode_labels.insert(default_mode_span, default_ref_mutbl); + // If our suggestion is to elide redundnt modes, this will be one of them. + if s.suggest_eliding_modes { + s.suggestion.push((pat.span.with_hi(ident.span.lo()), String::new())); + s.binding_mode_count += 1; + } } - if explicit_ba.0 == ByRef::No + if !s.suggest_eliding_modes + && explicit_ba.0 == ByRef::No && let ByRef::Yes(mutbl) = mode.0 { let sugg_str = match mutbl { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index 911b42c9ddfe..9ddc8912a514 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -32,7 +32,7 @@ fn main() { //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); - let &Foo(ref x) = &Foo(0); + let Foo(x) = &Foo(0); //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index ea3283d3a921..c36f92ecc7e0 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -52,10 +52,11 @@ note: matching on a reference type with a non-reference pattern changes the defa | LL | let Foo(ref x) = &Foo(0); | ^^^^^^^^^^ this matches on type `&_` -help: make the implied reference pattern explicit +help: remove the unnecessary binding modifier + | +LL - let Foo(ref x) = &Foo(0); +LL + let Foo(x) = &Foo(0); | -LL | let &Foo(ref x) = &Foo(0); - | + error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 --> $DIR/migration_lint.rs:40:13 diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index aaa448ea334f..0c6b2ff3a2f0 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -179,10 +179,11 @@ note: matching on a reference type with a non-reference pattern changes the defa | LL | test_pat_on_type![(ref x,): &(T,)]; | ^^^^^^^^ this matches on type `&_` -help: make the implied reference pattern explicit +help: remove the unnecessary binding modifier + | +LL - test_pat_on_type![(ref x,): &(T,)]; +LL + test_pat_on_type![(x,): &(T,)]; | -LL | test_pat_on_type![&(ref x,): &(T,)]; - | + error: binding modifiers may only be written when the default binding mode is `move` --> $DIR/min_match_ergonomics_fail.rs:34:20 @@ -196,10 +197,11 @@ note: matching on a reference type with a non-reference pattern changes the defa | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; | ^^^^^^^^^^^^ this matches on type `&mut _` -help: make the implied reference pattern explicit +help: remove the unnecessary binding modifier + | +LL - test_pat_on_type![(ref mut x,): &mut (T,)]; +LL + test_pat_on_type![(x,): &mut (T,)]; | -LL | test_pat_on_type![&mut (ref mut x,): &mut (T,)]; - | ++++ error: reference patterns may only be written when the default binding mode is `move` --> $DIR/min_match_ergonomics_fail.rs:43:10 From 8dcdb3eb3c28428267bd7bf4cb63e06f9e4330c1 Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 5 Feb 2025 09:27:59 -0800 Subject: [PATCH 12/13] peace of mind: be absolutely sure we don't try to emit a 0-part suggestion --- compiler/rustc_mir_build/src/errors.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 3707685b3add..07bdc59756aa 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1159,6 +1159,9 @@ impl Subdiagnostic for Rust2024IncompatiblePatSugg { }; format!("make the implied reference pattern{plural_derefs}{and_modes} explicit") }; - diag.multipart_suggestion_verbose(msg, self.suggestion, applicability); + // FIXME(dianne): for peace of mind, don't risk emitting a 0-part suggestion (that panics!) + if !self.suggestion.is_empty() { + diag.multipart_suggestion_verbose(msg, self.suggestion, applicability); + } } } From f1e4d94fa4bd253c26610e8d79d5da8b52bad99f Mon Sep 17 00:00:00 2001 From: dianne Date: Thu, 30 Jan 2025 21:42:31 -0800 Subject: [PATCH 13/13] add more pattern migration tests Most of these are meant to test possible future improvements, but since they cover cases the existing test suite didn't, I figure including them now may be helpful. --- .../migration_lint.fixed | 89 +++++++ .../migration_lint.rs | 89 +++++++ .../migration_lint.stderr | 223 +++++++++++++++++- 3 files changed, 400 insertions(+), 1 deletion(-) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index 9ddc8912a514..0a22e939496e 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -150,4 +150,93 @@ fn main() { let &[&(_)] = &[&0]; //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 + + // NB: Most of the following tests are for possible future improvements to migration suggestions + + // Test removing multiple binding modifiers. + let Struct { a, b, c } = &Struct { a: 0, b: 0, c: 0 }; + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(c, &0u32); + + // Test that we don't change bindings' modes when removing binding modifiers. + let &mut Struct { ref a, ref mut b, ref mut c } = &mut Struct { a: 0, b: 0, c: 0 }; + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, &mut 0u32); + assert_type_eq(c, &mut 0u32); + + // Test removing multiple reference patterns of various mutabilities, plus a binding modifier. + let &mut &Struct { a: &[ref a], b: &mut [&[ref b]], ref c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 }; + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, &0u32); + + // Test that we don't change bindings' types when removing reference patterns. + let &Foo(&ref a) = &Foo(&0); + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + + // Test that we don't change bindings' modes when adding reference paterns (caught early). + let &(&a, ref b, &[ref c], &mut [&mut (ref d, &[ref e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]); + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, 0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, &0u32); + assert_type_eq(d, &0u32); + assert_type_eq(e, &0u32); + + // Test that we don't change bindings' modes when adding reference patterns (caught late). + let &(ref a, &mut [ref b], &[mut c]) = &(0, &mut [0], &[0]); + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, 0u32); + + // Test featuring both additions and removals. + let &(&a, &mut (ref b, &[ref c])) = &(&0, &mut (0, &[0])); + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, 0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, &0u32); + + // Test that bindings' subpatterns' modes are updated properly. + let &[mut a @ ref b] = &[0]; + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, 0u32); + assert_type_eq(b, &0u32); + + // Test that bindings' subpatterns' modes are checked properly. + let &[ref a @ mut b] = &[0]; + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, 0u32); + + // Test that we respect bindings' subpatterns' types when rewriting `&ref x` to `x`. + let [&Foo(&ref a @ ref b), &Foo(&ref c @ d)] = [&Foo(&0); 2]; + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, &0u32); + assert_type_eq(d, 0u32); + + // Test that we respect bindings' subpatterns' modes when rewriting `&ref x` to `x`. + let [&Foo(&ref a @ [ref b]), &Foo(&ref c @ [d])] = [&Foo(&[0]); 2]; + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &[0u32]); + assert_type_eq(b, &0u32); + assert_type_eq(c, &[0u32]); + assert_type_eq(d, 0u32); } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index bf5fd780404b..7a6f2269d44a 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -150,4 +150,93 @@ fn main() { let [&(_)] = &[&0]; //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 //~| WARN: this changes meaning in Rust 2024 + + // NB: Most of the following tests are for possible future improvements to migration suggestions + + // Test removing multiple binding modifiers. + let Struct { ref a, ref b, c } = &Struct { a: 0, b: 0, c: 0 }; + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(c, &0u32); + + // Test that we don't change bindings' modes when removing binding modifiers. + let Struct { ref a, ref mut b, c } = &mut Struct { a: 0, b: 0, c: 0 }; + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, &mut 0u32); + assert_type_eq(c, &mut 0u32); + + // Test removing multiple reference patterns of various mutabilities, plus a binding modifier. + let Struct { a: &[ref a], b: &mut [[b]], c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 }; + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, &0u32); + + // Test that we don't change bindings' types when removing reference patterns. + let Foo(&ref a) = &Foo(&0); + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + + // Test that we don't change bindings' modes when adding reference paterns (caught early). + let (&a, b, [c], [(d, [e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]); + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, 0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, &0u32); + assert_type_eq(d, &0u32); + assert_type_eq(e, &0u32); + + // Test that we don't change bindings' modes when adding reference patterns (caught late). + let (a, [b], [mut c]) = &(0, &mut [0], &[0]); + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, 0u32); + + // Test featuring both additions and removals. + let (&a, (b, &[ref c])) = &(&0, &mut (0, &[0])); + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, 0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, &0u32); + + // Test that bindings' subpatterns' modes are updated properly. + let [mut a @ b] = &[0]; + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, 0u32); + assert_type_eq(b, &0u32); + + // Test that bindings' subpatterns' modes are checked properly. + let [a @ mut b] = &[0]; + //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, 0u32); + + // Test that we respect bindings' subpatterns' types when rewriting `&ref x` to `x`. + let [Foo(&ref a @ ref b), Foo(&ref c @ d)] = [&Foo(&0); 2]; + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &0u32); + assert_type_eq(b, &0u32); + assert_type_eq(c, &0u32); + assert_type_eq(d, 0u32); + + // Test that we respect bindings' subpatterns' modes when rewriting `&ref x` to `x`. + let [Foo(&ref a @ [ref b]), Foo(&ref c @ [d])] = [&Foo(&[0]); 2]; + //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + assert_type_eq(a, &[0u32]); + assert_type_eq(b, &0u32); + assert_type_eq(c, &[0u32]); + assert_type_eq(d, 0u32); } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index c36f92ecc7e0..191800df07a2 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -341,5 +341,226 @@ help: make the implied reference pattern explicit LL | let &[&(_)] = &[&0]; | + -error: aborting due to 18 previous errors +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:157:18 + | +LL | let Struct { ref a, ref b, c } = &Struct { a: 0, b: 0, c: 0 }; + | ^^^ ^^^ binding modifier not allowed under `ref` default binding mode + | | + | binding modifier not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:157:9 + | +LL | let Struct { ref a, ref b, c } = &Struct { a: 0, b: 0, c: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_` +help: remove the unnecessary binding modifiers + | +LL - let Struct { ref a, ref b, c } = &Struct { a: 0, b: 0, c: 0 }; +LL + let Struct { a, b, c } = &Struct { a: 0, b: 0, c: 0 }; + | + +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:164:18 + | +LL | let Struct { ref a, ref mut b, c } = &mut Struct { a: 0, b: 0, c: 0 }; + | ^^^ ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode + | | + | binding modifier not allowed under `ref mut` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:164:9 + | +LL | let Struct { ref a, ref mut b, c } = &mut Struct { a: 0, b: 0, c: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&mut _` +help: make the implied reference pattern and variable binding mode explicit + | +LL | let &mut Struct { ref a, ref mut b, ref mut c } = &mut Struct { a: 0, b: 0, c: 0 }; + | ++++ +++++++ + +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:172:21 + | +LL | let Struct { a: &[ref a], b: &mut [[b]], c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 }; + | ^ ^^^^ reference pattern not allowed under `ref` default binding mode + | | + | reference pattern not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:172:9 + | +LL | let Struct { a: &[ref a], b: &mut [[b]], c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_` +help: make the implied reference patterns and variable binding modes explicit + | +LL | let &mut &Struct { a: &[ref a], b: &mut [&[ref b]], ref c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 }; + | ++++++ + +++ +++ + +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:180:13 + | +LL | let Foo(&ref a) = &Foo(&0); + | ^ reference pattern not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:180:9 + | +LL | let Foo(&ref a) = &Foo(&0); + | ^^^^^^^^^^^ this matches on type `&_` +help: make the implied reference pattern explicit + | +LL | let &Foo(&ref a) = &Foo(&0); + | + + +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:186:10 + | +LL | let (&a, b, [c], [(d, [e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]); + | ^ reference pattern not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:186:9 + | +LL | let (&a, b, [c], [(d, [e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_` +help: make the implied reference patterns and variable binding modes explicit + | +LL | let &(&a, ref b, &[ref c], &mut [&mut (ref d, &[ref e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]); + | + +++ + +++ ++++ ++++ +++ + +++ + +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:196:19 + | +LL | let (a, [b], [mut c]) = &(0, &mut [0], &[0]); + | ^^^ binding modifier not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:196:9 + | +LL | let (a, [b], [mut c]) = &(0, &mut [0], &[0]); + | ^^^^^^^^^^^^^^^^^ this matches on type `&_` +help: make the implied reference patterns and variable binding modes explicit + | +LL | let &(ref a, &mut [ref b], &[mut c]) = &(0, &mut [0], &[0]); + | + +++ ++++ +++ + + +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:204:10 + | +LL | let (&a, (b, &[ref c])) = &(&0, &mut (0, &[0])); + | ^ ^ reference pattern not allowed under `ref` default binding mode + | | + | reference pattern not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:204:9 + | +LL | let (&a, (b, &[ref c])) = &(&0, &mut (0, &[0])); + | ^^^^^^^^^^^^^^^^^^^ this matches on type `&_` +help: make the implied reference patterns and variable binding mode explicit + | +LL | let &(&a, &mut (ref b, &[ref c])) = &(&0, &mut (0, &[0])); + | + ++++ +++ + +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:212:10 + | +LL | let [mut a @ b] = &[0]; + | ^^^ binding modifier not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:212:9 + | +LL | let [mut a @ b] = &[0]; + | ^^^^^^^^^^^ this matches on type `&_` +help: make the implied reference pattern and variable binding mode explicit + | +LL | let &[mut a @ ref b] = &[0]; + | + +++ + +error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:219:14 + | +LL | let [a @ mut b] = &[0]; + | ^^^ binding modifier not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:219:9 + | +LL | let [a @ mut b] = &[0]; + | ^^^^^^^^^^^ this matches on type `&_` +help: make the implied reference pattern and variable binding mode explicit + | +LL | let &[ref a @ mut b] = &[0]; + | + +++ + +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:226:14 + | +LL | let [Foo(&ref a @ ref b), Foo(&ref c @ d)] = [&Foo(&0); 2]; + | ^ ^ reference pattern not allowed under `ref` default binding mode + | | + | reference pattern not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:226:31 + | +LL | let [Foo(&ref a @ ref b), Foo(&ref c @ d)] = [&Foo(&0); 2]; + | ^^^^^^^^^^^^^^^ this matches on type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:226:10 + | +LL | let [Foo(&ref a @ ref b), Foo(&ref c @ d)] = [&Foo(&0); 2]; + | ^^^^^^^^^^^^^^^^^^^ this matches on type `&_` +help: make the implied reference patterns explicit + | +LL | let [&Foo(&ref a @ ref b), &Foo(&ref c @ d)] = [&Foo(&0); 2]; + | + + + +error: reference patterns may only be written when the default binding mode is `move` in Rust 2024 + --> $DIR/migration_lint.rs:235:14 + | +LL | let [Foo(&ref a @ [ref b]), Foo(&ref c @ [d])] = [&Foo(&[0]); 2]; + | ^ ^ reference pattern not allowed under `ref` default binding mode + | | + | reference pattern not allowed under `ref` default binding mode + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:235:33 + | +LL | let [Foo(&ref a @ [ref b]), Foo(&ref c @ [d])] = [&Foo(&[0]); 2]; + | ^^^^^^^^^^^^^^^^^ this matches on type `&_` +note: matching on a reference type with a non-reference pattern changes the default binding mode + --> $DIR/migration_lint.rs:235:10 + | +LL | let [Foo(&ref a @ [ref b]), Foo(&ref c @ [d])] = [&Foo(&[0]); 2]; + | ^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_` +help: make the implied reference patterns explicit + | +LL | let [&Foo(&ref a @ [ref b]), &Foo(&ref c @ [d])] = [&Foo(&[0]); 2]; + | + + + +error: aborting due to 29 previous errors