Skip to content

Commit 2ee601c

Browse files
committed
highlight the whole problem subpattern when pointing out the default binding mode
(cherry picked from commit 4331f55)
1 parent f8b23cd commit 2ee601c

File tree

5 files changed

+129
-45
lines changed

5 files changed

+129
-45
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2649,29 +2649,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26492649
// error if the subpattern is of edition >= 2024.
26502650
let trimmed_span = subpat.span.until(cutoff_span).with_ctxt(subpat.span.ctxt());
26512651

2652+
let mut typeck_results = self.typeck_results.borrow_mut();
2653+
let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
2654+
let info = table.entry(pat_id).or_default();
2655+
2656+
info.primary_spans.push(trimmed_span);
2657+
26522658
// Only provide a detailed label if the problematic subpattern isn't from an expansion.
26532659
// In the case that it's from a macro, we'll add a more detailed note in the emitter.
2654-
let desc = if subpat.span.from_expansion() {
2660+
let from_expansion = subpat.span.from_expansion();
2661+
let primary_label = if from_expansion {
26552662
// NB: This wording assumes the only expansions that can produce problematic reference
26562663
// patterns and bindings are macros. If a desugaring or AST pass is added that can do
26572664
// so, we may want to inspect the span's source callee or macro backtrace.
26582665
"occurs within macro expansion"
26592666
} else {
2660-
match def_br_mutbl {
2661-
Mutability::Not => "default binding mode is `ref`",
2662-
Mutability::Mut => "default binding mode is `ref mut`",
2667+
if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) {
2668+
info.bad_modifiers |= true;
2669+
"this binding modifier"
2670+
} else {
2671+
info.bad_ref_pats |= true;
2672+
"this reference pattern"
26632673
}
26642674
};
2675+
info.span_labels.push((trimmed_span, primary_label.to_owned()));
26652676

2666-
let mut typeck_results = self.typeck_results.borrow_mut();
2667-
let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
2668-
let info = table.entry(pat_id).or_default();
2669-
2670-
info.labels.push((trimmed_span, desc.to_owned()));
2671-
if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) {
2672-
info.bad_modifiers |= true;
2673-
} else {
2674-
info.bad_ref_pats |= true;
2677+
if !from_expansion {
2678+
// Add a secondary label covering the whole pattern noting the default binding mode
2679+
let def_br_desc = match def_br_mutbl {
2680+
Mutability::Not => "default binding mode is `ref`",
2681+
Mutability::Mut => "default binding mode is `ref mut`",
2682+
};
2683+
info.span_labels.push((subpat.span, def_br_desc.to_owned()));
26752684
}
26762685
}
26772686
}

compiler/rustc_middle/src/ty/typeck_results.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -816,8 +816,10 @@ impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> {
816816
/// emitted during THIR construction.
817817
#[derive(TyEncodable, TyDecodable, Debug, HashStable, Default)]
818818
pub struct Rust2024IncompatiblePatInfo {
819-
/// Labels for subpatterns incompatible with Rust 2024.
820-
pub labels: Vec<(Span, String)>,
819+
/// Spans for `&`s, `&mut`s, and binding modifiers incompatible with Rust 2024.
820+
pub primary_spans: Vec<Span>,
821+
/// Labels for the primary spans and their patterns, to provide additional context.
822+
pub span_labels: Vec<(Span, String)>,
821823
/// Whether any binding modifiers occur under a non-`move` default binding mode.
822824
pub bad_modifiers: bool,
823825
/// Whether any `&` or `&mut` patterns occur under a non-`move` default binding mode.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
5959
debug!("pat_from_hir({:?}) = {:?}", pat, result);
6060
if let Some(info) = migration_info {
6161
let sugg = pcx.rust_2024_migration_suggestion.expect("suggestion should be present");
62-
let mut spans = MultiSpan::from_spans(info.labels.iter().map(|(span, _)| *span).collect());
63-
for (span, label) in &info.labels {
62+
let mut spans = MultiSpan::from_spans(info.primary_spans.clone());
63+
for (span, label) in &info.span_labels {
6464
spans.push_span_label(*span, label.clone());
6565
}
6666
// If a relevant span is from at least edition 2024, this is a hard error.

tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: binding modifiers may only be written when the default binding mode is `m
22
--> $DIR/migration_lint.rs:25:13
33
|
44
LL | let Foo(mut x) = &Foo(0);
5-
| ^^^ default binding mode is `ref`
5+
| ^^^--
6+
| |
7+
| this binding modifier
8+
| default binding mode is `ref`
69
|
710
= warning: this changes meaning in Rust 2024
811
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -20,7 +23,10 @@ error: binding modifiers may only be written when the default binding mode is `m
2023
--> $DIR/migration_lint.rs:30:13
2124
|
2225
LL | let Foo(mut x) = &mut Foo(0);
23-
| ^^^ default binding mode is `ref mut`
26+
| ^^^--
27+
| |
28+
| this binding modifier
29+
| default binding mode is `ref mut`
2430
|
2531
= warning: this changes meaning in Rust 2024
2632
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -33,7 +39,10 @@ error: binding modifiers may only be written when the default binding mode is `m
3339
--> $DIR/migration_lint.rs:35:13
3440
|
3541
LL | let Foo(ref x) = &Foo(0);
36-
| ^^^ default binding mode is `ref`
42+
| ^^^--
43+
| |
44+
| this binding modifier
45+
| default binding mode is `ref`
3746
|
3847
= warning: this changes meaning in Rust 2024
3948
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -46,7 +55,10 @@ error: binding modifiers may only be written when the default binding mode is `m
4655
--> $DIR/migration_lint.rs:40:13
4756
|
4857
LL | let Foo(ref x) = &mut Foo(0);
49-
| ^^^ default binding mode is `ref mut`
58+
| ^^^--
59+
| |
60+
| this binding modifier
61+
| default binding mode is `ref mut`
5062
|
5163
= warning: this changes meaning in Rust 2024
5264
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -59,7 +71,10 @@ error: reference patterns may only be written when the default binding mode is `
5971
--> $DIR/migration_lint.rs:57:13
6072
|
6173
LL | let Foo(&x) = &Foo(&0);
62-
| ^ default binding mode is `ref`
74+
| ^-
75+
| |
76+
| this reference pattern
77+
| default binding mode is `ref`
6378
|
6479
= warning: this changes meaning in Rust 2024
6580
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -72,7 +87,10 @@ error: reference patterns may only be written when the default binding mode is `
7287
--> $DIR/migration_lint.rs:62:13
7388
|
7489
LL | let Foo(&mut x) = &Foo(&mut 0);
75-
| ^^^^ default binding mode is `ref`
90+
| ^^^^--
91+
| |
92+
| this reference pattern
93+
| default binding mode is `ref`
7694
|
7795
= warning: this changes meaning in Rust 2024
7896
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -85,7 +103,10 @@ error: reference patterns may only be written when the default binding mode is `
85103
--> $DIR/migration_lint.rs:67:13
86104
|
87105
LL | let Foo(&x) = &mut Foo(&0);
88-
| ^ default binding mode is `ref mut`
106+
| ^-
107+
| |
108+
| this reference pattern
109+
| default binding mode is `ref mut`
89110
|
90111
= warning: this changes meaning in Rust 2024
91112
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -98,7 +119,10 @@ error: reference patterns may only be written when the default binding mode is `
98119
--> $DIR/migration_lint.rs:72:13
99120
|
100121
LL | let Foo(&mut x) = &mut Foo(&mut 0);
101-
| ^^^^ default binding mode is `ref mut`
122+
| ^^^^--
123+
| |
124+
| this reference pattern
125+
| default binding mode is `ref mut`
102126
|
103127
= warning: this changes meaning in Rust 2024
104128
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -111,7 +135,10 @@ error: reference patterns may only be written when the default binding mode is `
111135
--> $DIR/migration_lint.rs:81:17
112136
|
113137
LL | if let Some(&x) = &&&&&Some(&0u8) {
114-
| ^ default binding mode is `ref`
138+
| ^-
139+
| |
140+
| this reference pattern
141+
| default binding mode is `ref`
115142
|
116143
= warning: this changes meaning in Rust 2024
117144
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -124,7 +151,10 @@ error: reference patterns may only be written when the default binding mode is `
124151
--> $DIR/migration_lint.rs:87:17
125152
|
126153
LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) {
127-
| ^^^^ default binding mode is `ref`
154+
| ^^^^--
155+
| |
156+
| this reference pattern
157+
| default binding mode is `ref`
128158
|
129159
= warning: this changes meaning in Rust 2024
130160
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -137,7 +167,10 @@ error: reference patterns may only be written when the default binding mode is `
137167
--> $DIR/migration_lint.rs:93:17
138168
|
139169
LL | if let Some(&x) = &&&&&mut Some(&0u8) {
140-
| ^ default binding mode is `ref`
170+
| ^-
171+
| |
172+
| this reference pattern
173+
| default binding mode is `ref`
141174
|
142175
= warning: this changes meaning in Rust 2024
143176
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -150,7 +183,10 @@ error: reference patterns may only be written when the default binding mode is `
150183
--> $DIR/migration_lint.rs:99:17
151184
|
152185
LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) {
153-
| ^^^^ default binding mode is `ref mut`
186+
| ^^^^--------------
187+
| |
188+
| this reference pattern
189+
| default binding mode is `ref mut`
154190
|
155191
= warning: this changes meaning in Rust 2024
156192
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -163,7 +199,10 @@ error: binding modifiers may only be written when the default binding mode is `m
163199
--> $DIR/migration_lint.rs:111:21
164200
|
165201
LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 };
166-
| ^^^ default binding mode is `ref`
202+
| ^^^--
203+
| |
204+
| this binding modifier
205+
| default binding mode is `ref`
167206
|
168207
= warning: this changes meaning in Rust 2024
169208
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -176,8 +215,11 @@ error: binding modifiers and reference patterns may only be written when the def
176215
--> $DIR/migration_lint.rs:117:21
177216
|
178217
LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 };
179-
| ^ ^^^ default binding mode is `ref`
180-
| |
218+
| ^- ^^^--
219+
| | |
220+
| | this binding modifier
221+
| | default binding mode is `ref`
222+
| this reference pattern
181223
| default binding mode is `ref`
182224
|
183225
= warning: this changes meaning in Rust 2024
@@ -191,8 +233,11 @@ error: reference patterns may only be written when the default binding mode is `
191233
--> $DIR/migration_lint.rs:124:24
192234
|
193235
LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } =
194-
| ^ ^ default binding mode is `ref`
195-
| |
236+
| ^------- ^-
237+
| | |
238+
| | this reference pattern
239+
| | default binding mode is `ref`
240+
| this reference pattern
196241
| default binding mode is `ref`
197242
|
198243
= 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
206251
--> $DIR/migration_lint.rs:137:15
207252
|
208253
LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
209-
| ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion
254+
| ^^^-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion
210255
| |
256+
| this binding modifier
211257
| default binding mode is `ref`
212258
|
213259
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
@@ -221,8 +267,11 @@ error: binding modifiers and reference patterns may only be written when the def
221267
--> $DIR/migration_lint.rs:145:10
222268
|
223269
LL | let [&mut [ref a]] = &mut [&mut &[0]];
224-
| ^^^^ ^^^ default binding mode is `ref`
225-
| |
270+
| ^^^^--^^^---
271+
| | |
272+
| | this binding modifier
273+
| | default binding mode is `ref`
274+
| this reference pattern
226275
| default binding mode is `ref mut`
227276
|
228277
= warning: this changes meaning in Rust 2024
@@ -236,7 +285,10 @@ error: reference patterns may only be written when the default binding mode is `
236285
--> $DIR/migration_lint.rs:150:10
237286
|
238287
LL | let [&(_)] = &[&0];
239-
| ^^ default binding mode is `ref`
288+
| ^^--
289+
| |
290+
| this reference pattern
291+
| default binding mode is `ref`
240292
|
241293
= warning: this changes meaning in Rust 2024
242294
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>

tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ error: reference patterns may only be written when the default binding mode is `
103103
--> $DIR/min_match_ergonomics_fail.rs:24:20
104104
|
105105
LL | test_pat_on_type![(&x,): &(&T,)];
106-
| ^ default binding mode is `ref`
106+
| ^-
107+
| |
108+
| this reference pattern
109+
| default binding mode is `ref`
107110
|
108111
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
109112
help: make the implied reference pattern explicit
@@ -115,7 +118,10 @@ error: reference patterns may only be written when the default binding mode is `
115118
--> $DIR/min_match_ergonomics_fail.rs:27:20
116119
|
117120
LL | test_pat_on_type![(&mut x,): &(&mut T,)];
118-
| ^^^^ default binding mode is `ref`
121+
| ^^^^--
122+
| |
123+
| this reference pattern
124+
| default binding mode is `ref`
119125
|
120126
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
121127
help: make the implied reference pattern explicit
@@ -127,7 +133,10 @@ error: reference patterns may only be written when the default binding mode is `
127133
--> $DIR/min_match_ergonomics_fail.rs:31:28
128134
|
129135
LL | test_pat_on_type![Foo { f: &(x,) }: &Foo];
130-
| ^ default binding mode is `ref`
136+
| ^----
137+
| |
138+
| this reference pattern
139+
| default binding mode is `ref`
131140
|
132141
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
133142
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
139148
--> $DIR/min_match_ergonomics_fail.rs:32:20
140149
|
141150
LL | test_pat_on_type![(mut x,): &(T,)];
142-
| ^^^ default binding mode is `ref`
151+
| ^^^--
152+
| |
153+
| this binding modifier
154+
| default binding mode is `ref`
143155
|
144156
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
145157
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
151163
--> $DIR/min_match_ergonomics_fail.rs:33:20
152164
|
153165
LL | test_pat_on_type![(ref x,): &(T,)];
154-
| ^^^ default binding mode is `ref`
166+
| ^^^--
167+
| |
168+
| this binding modifier
169+
| default binding mode is `ref`
155170
|
156171
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
157172
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
163178
--> $DIR/min_match_ergonomics_fail.rs:34:20
164179
|
165180
LL | test_pat_on_type![(ref mut x,): &mut (T,)];
166-
| ^^^^^^^ default binding mode is `ref mut`
181+
| ^^^^^^^--
182+
| |
183+
| this binding modifier
184+
| default binding mode is `ref mut`
167185
|
168186
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
169187
help: make the implied reference pattern explicit
@@ -175,7 +193,10 @@ error: reference patterns may only be written when the default binding mode is `
175193
--> $DIR/min_match_ergonomics_fail.rs:43:10
176194
|
177195
LL | (&x,) => x,
178-
| ^ default binding mode is `ref`
196+
| ^-
197+
| |
198+
| this reference pattern
199+
| default binding mode is `ref`
179200
|
180201
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
181202
help: make the implied reference pattern explicit

0 commit comments

Comments
 (0)