Skip to content

Commit 271e81f

Browse files
committed
clarify wording of match ergonomics diagnostics
1 parent 3014e79 commit 271e81f

19 files changed

+585
-456
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3113,20 +3113,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31133113
// binding mode. This keeps it from making those suggestions, as doing so could panic.
31143114
let info = table.entry(pat_id).or_insert_with(|| ty::Rust2024IncompatiblePatInfo {
31153115
primary_labels: Vec::new(),
3116-
bad_modifiers: false,
3116+
bad_ref_modifiers: false,
3117+
bad_mut_modifiers: false,
31173118
bad_ref_pats: false,
31183119
suggest_eliding_modes: !self.tcx.features().ref_pat_eat_one_layer_2024()
31193120
&& !self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
31203121
});
31213122

31223123
let pat_kind = if let PatKind::Binding(user_bind_annot, _, _, _) = subpat.kind {
3123-
info.bad_modifiers = true;
31243124
// If the user-provided binding modifier doesn't match the default binding mode, we'll
31253125
// need to suggest reference patterns, which can affect other bindings.
31263126
// For simplicity, we opt to suggest making the pattern fully explicit.
31273127
info.suggest_eliding_modes &=
31283128
user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not);
3129-
"binding modifier"
3129+
if user_bind_annot == BindingMode(ByRef::No, Mutability::Mut) {
3130+
info.bad_mut_modifiers = true;
3131+
"`mut` binding modifier"
3132+
} else {
3133+
info.bad_ref_modifiers = true;
3134+
match user_bind_annot.1 {
3135+
Mutability::Not => "explicit `ref` binding modifier",
3136+
Mutability::Mut => "explicit `ref mut` binding modifier",
3137+
}
3138+
}
31303139
} else {
31313140
info.bad_ref_pats = true;
31323141
// For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll
@@ -3145,11 +3154,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31453154
// so, we may want to inspect the span's source callee or macro backtrace.
31463155
"occurs within macro expansion".to_owned()
31473156
} else {
3148-
let dbm_str = match def_br_mutbl {
3149-
Mutability::Not => "ref",
3150-
Mutability::Mut => "ref mut",
3151-
};
3152-
format!("{pat_kind} not allowed under `{dbm_str}` default binding mode")
3157+
format!("{pat_kind} not allowed when implicitly borrowing")
31533158
};
31543159
info.primary_labels.push((trimmed_span, primary_label));
31553160
}

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ declare_lint! {
15991599
"detects patterns whose meaning will change in Rust 2024",
16001600
@future_incompatible = FutureIncompatibleInfo {
16011601
reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
1602-
reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>",
1602+
reference: "<https://doc.rust-lang.org/edition-guide/rust-2024/match-ergonomics.html>",
16031603
};
16041604
}
16051605

compiler/rustc_middle/src/ty/typeck_results.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,8 +841,10 @@ impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> {
841841
pub struct Rust2024IncompatiblePatInfo {
842842
/// Labeled spans for `&`s, `&mut`s, and binding modifiers incompatible with Rust 2024.
843843
pub primary_labels: Vec<(Span, String)>,
844-
/// Whether any binding modifiers occur under a non-`move` default binding mode.
845-
pub bad_modifiers: bool,
844+
/// Whether any `mut` binding modifiers occur under a non-`move` default binding mode.
845+
pub bad_mut_modifiers: bool,
846+
/// Whether any `ref`/`ref mut` binding modifiers occur under a non-`move` default binding mode.
847+
pub bad_ref_modifiers: bool,
846848
/// Whether any `&` or `&mut` patterns occur under a non-`move` default binding mode.
847849
pub bad_ref_pats: bool,
848850
/// If `true`, we can give a simpler suggestion solely by eliding explicit binding modifiers.

compiler/rustc_mir_build/messages.ftl

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -318,13 +318,25 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from
318318
319319
mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
320320
321-
mir_build_rust_2024_incompatible_pat = {$bad_modifiers ->
322-
*[true] binding modifiers{$bad_ref_pats ->
323-
*[true] {" "}and reference patterns
321+
mir_build_rust_2024_incompatible_pat = cannot {$bad_mut_modifiers ->
322+
*[true] {$bad_ref_modifiers ->
323+
*[true] write explicit binding modifiers
324+
[false] mutably bind by value
325+
}{$bad_ref_pats ->
326+
*[true] {" "}or explicitly dereference
324327
[false] {""}
325328
}
326-
[false] reference patterns
327-
} may only be written when the default binding mode is `move`{$is_hard_error ->
329+
[false] {$bad_ref_modifiers ->
330+
*[true] explicitly borrow{$bad_ref_pats ->
331+
*[true] {" "}or dereference
332+
[false] {""}
333+
}
334+
[false] {$bad_ref_pats ->
335+
*[true] explicitly dereference
336+
[false] {""}
337+
}
338+
}
339+
} within an implicitly-borrowing pattern{$is_hard_error ->
328340
*[true] {""}
329341
[false] {" "}in Rust 2024
330342
}

compiler/rustc_mir_build/src/errors.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,8 @@ pub(crate) enum MiscPatternSuggestion {
11011101
pub(crate) struct Rust2024IncompatiblePat {
11021102
#[subdiagnostic]
11031103
pub(crate) sugg: Rust2024IncompatiblePatSugg,
1104-
pub(crate) bad_modifiers: bool,
1104+
pub(crate) bad_mut_modifiers: bool,
1105+
pub(crate) bad_ref_modifiers: bool,
11051106
pub(crate) bad_ref_pats: bool,
11061107
pub(crate) is_hard_error: bool,
11071108
}
@@ -1124,9 +1125,11 @@ impl Subdiagnostic for Rust2024IncompatiblePatSugg {
11241125
for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() {
11251126
// Don't point to a macro call site.
11261127
if !span.from_expansion() {
1127-
let note_msg = "matching on a reference type with a non-reference pattern changes the default binding mode";
1128-
let label_msg =
1129-
format!("this matches on type `{}_`", def_br_mutbl.ref_prefix_str());
1128+
let note_msg = "matching on a reference type with a non-reference pattern implicitly borrows the contents";
1129+
let label_msg = format!(
1130+
"this non-reference pattern matches on a reference type `{}_`",
1131+
def_br_mutbl.ref_prefix_str()
1132+
);
11301133
let mut label = MultiSpan::from(span);
11311134
label.push_span_label(span, label_msg);
11321135
diag.span_note(label, note_msg);
@@ -1140,17 +1143,21 @@ impl Subdiagnostic for Rust2024IncompatiblePatSugg {
11401143
} else {
11411144
Applicability::MaybeIncorrect
11421145
};
1146+
let plural_modes = pluralize!(self.binding_mode_count);
11431147
let msg = if self.suggest_eliding_modes {
1144-
let plural_modes = pluralize!(self.binding_mode_count);
11451148
format!("remove the unnecessary binding modifier{plural_modes}")
11461149
} else {
1147-
let plural_derefs = pluralize!(self.ref_pattern_count);
1148-
let and_modes = if self.binding_mode_count > 0 {
1149-
format!(" and variable binding mode{}", pluralize!(self.binding_mode_count))
1150+
let and_add_modes = if self.binding_mode_count > 0 {
1151+
let a = if self.binding_mode_count == 1 { "a " } else { "" };
1152+
format!(" and borrow explicitly using {a}variable binding mode{plural_modes}",)
11501153
} else {
11511154
String::new()
11521155
};
1153-
format!("make the implied reference pattern{plural_derefs}{and_modes} explicit")
1156+
if self.ref_pattern_count == 1 {
1157+
format!("match on the reference with a reference pattern{and_add_modes}")
1158+
} else {
1159+
format!("match on references with reference patterns{and_add_modes}")
1160+
}
11541161
};
11551162
// FIXME(dianne): for peace of mind, don't risk emitting a 0-part suggestion (that panics!)
11561163
if !self.suggestion.is_empty() {

compiler/rustc_mir_build/src/thir/pattern/migration.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ impl<'a> PatMigration<'a> {
6565
// provide the same reference link as the lint
6666
err.note(format!("for more information, see {}", info.reference));
6767
}
68-
err.arg("bad_modifiers", self.info.bad_modifiers);
68+
err.arg("bad_mut_modifiers", self.info.bad_mut_modifiers);
69+
err.arg("bad_ref_modifiers", self.info.bad_ref_modifiers);
6970
err.arg("bad_ref_pats", self.info.bad_ref_pats);
7071
err.arg("is_hard_error", true);
7172
err.subdiagnostic(sugg);
@@ -77,7 +78,8 @@ impl<'a> PatMigration<'a> {
7778
spans,
7879
Rust2024IncompatiblePat {
7980
sugg,
80-
bad_modifiers: self.info.bad_modifiers,
81+
bad_mut_modifiers: self.info.bad_mut_modifiers,
82+
bad_ref_modifiers: self.info.bad_ref_modifiers,
8183
bad_ref_pats: self.info.bad_ref_pats,
8284
is_hard_error,
8385
},

tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,20 @@ LL | let [&bind_ref_mut!(x)] = &mut [0];
5959
| |
6060
| help: replace this `&` with `&mut`: `&mut`
6161

62-
error: binding modifiers may only be written when the default binding mode is `move`
62+
error: cannot explicitly borrow within an implicitly-borrowing pattern
6363
--> $DIR/mixed-editions.rs:30:10
6464
|
6565
LL | let [bind_ref!(y)] = &[0];
6666
| ^^^^^^^^^^^^ occurs within macro expansion
6767
|
68-
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
69-
note: matching on a reference type with a non-reference pattern changes the default binding mode
68+
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/match-ergonomics.html>
69+
note: matching on a reference type with a non-reference pattern implicitly borrows the contents
7070
--> $DIR/mixed-editions.rs:30:9
7171
|
7272
LL | let [bind_ref!(y)] = &[0];
73-
| ^^^^^^^^^^^^^^ this matches on type `&_`
73+
| ^^^^^^^^^^^^^^ this non-reference pattern matches on a reference type `&_`
7474
= note: this error originates in the macro `bind_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
75-
help: make the implied reference pattern explicit
75+
help: match on the reference with a reference pattern
7676
|
7777
LL | let &[bind_ref!(y)] = &[0];
7878
| +

tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ LL | let [&bind_ref_mut!(x)] = &mut [0];
5858
| |
5959
| help: replace this `&` with `&mut`: `&mut`
6060

61-
error: binding modifiers may only be written when the default binding mode is `move`
61+
error: cannot explicitly borrow within an implicitly-borrowing pattern
6262
--> $DIR/mixed-editions.rs:26:21
6363
|
6464
LL | let match_ctor!(ref x) = &[0];
65-
| ^^^ binding modifier not allowed under `ref` default binding mode
65+
| ^^^ explicit `ref` binding modifier not allowed when implicitly borrowing
6666
|
67-
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
68-
help: make the implied reference pattern explicit
67+
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/match-ergonomics.html>
68+
help: match on the reference with a reference pattern
6969
--> $DIR/auxiliary/mixed-editions-macros.rs:11:9
7070
|
7171
LL | &[$p]

tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ fn assert_type_eq<T, U: Eq<T>>(_: T, _: U) {}
2424
/// only when the binding is from edition 2024.
2525
fn ref_binding_tests() {
2626
let match_ctor!(ref x) = &[0];
27-
//[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
27+
//[classic2024,structural2024]~^ ERROR: cannot explicitly borrow within an implicitly-borrowing pattern
2828
#[cfg(any(classic2021, structural2021))] assert_type_eq(x, &0u32);
2929

3030
let [bind_ref!(y)] = &[0];
31-
//[classic2021,structural2021]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
31+
//[classic2021,structural2021]~^ ERROR: cannot explicitly borrow within an implicitly-borrowing pattern
3232
#[cfg(any(classic2024, structural2024))] assert_type_eq(y, &0u32);
3333
}
3434

tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,20 @@ LL | let [&bind_ref_mut!(x)] = &mut [0];
3737
| |
3838
| help: replace this `&` with `&mut`: `&mut`
3939

40-
error: binding modifiers may only be written when the default binding mode is `move`
40+
error: cannot explicitly borrow within an implicitly-borrowing pattern
4141
--> $DIR/mixed-editions.rs:30:10
4242
|
4343
LL | let [bind_ref!(y)] = &[0];
4444
| ^^^^^^^^^^^^ occurs within macro expansion
4545
|
46-
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
47-
note: matching on a reference type with a non-reference pattern changes the default binding mode
46+
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/match-ergonomics.html>
47+
note: matching on a reference type with a non-reference pattern implicitly borrows the contents
4848
--> $DIR/mixed-editions.rs:30:9
4949
|
5050
LL | let [bind_ref!(y)] = &[0];
51-
| ^^^^^^^^^^^^^^ this matches on type `&_`
51+
| ^^^^^^^^^^^^^^ this non-reference pattern matches on a reference type `&_`
5252
= note: this error originates in the macro `bind_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
53-
help: make the implied reference pattern explicit
53+
help: match on the reference with a reference pattern
5454
|
5555
LL | let &[bind_ref!(y)] = &[0];
5656
| +

0 commit comments

Comments
 (0)