Skip to content

Commit 4331f55

Browse files
committed
highlight the whole problem subpattern when pointing out the default binding mode
1 parent 9202001 commit 4331f55

File tree

7 files changed

+189
-60
lines changed

7 files changed

+189
-60
lines changed

compiler/rustc_hir_typeck/src/pat.rs

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

2787+
let mut typeck_results = self.typeck_results.borrow_mut();
2788+
let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
2789+
let info = table.entry(pat_id).or_default();
2790+
2791+
info.primary_spans.push(trimmed_span);
2792+
27872793
// Only provide a detailed label if the problematic subpattern isn't from an expansion.
27882794
// In the case that it's from a macro, we'll add a more detailed note in the emitter.
2789-
let desc = if subpat.span.from_expansion() {
2795+
let from_expansion = subpat.span.from_expansion();
2796+
let primary_label = if from_expansion {
27902797
// NB: This wording assumes the only expansions that can produce problematic reference
27912798
// patterns and bindings are macros. If a desugaring or AST pass is added that can do
27922799
// so, we may want to inspect the span's source callee or macro backtrace.
27932800
"occurs within macro expansion"
27942801
} else {
2795-
match def_br_mutbl {
2796-
Mutability::Not => "default binding mode is `ref`",
2797-
Mutability::Mut => "default binding mode is `ref mut`",
2802+
if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) {
2803+
info.bad_modifiers |= true;
2804+
"this binding modifier"
2805+
} else {
2806+
info.bad_ref_pats |= true;
2807+
"this reference pattern"
27982808
}
27992809
};
2810+
info.span_labels.push((trimmed_span, primary_label.to_owned()));
28002811

2801-
let mut typeck_results = self.typeck_results.borrow_mut();
2802-
let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
2803-
let info = table.entry(pat_id).or_default();
2804-
2805-
info.labels.push((trimmed_span, desc.to_owned()));
2806-
if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) {
2807-
info.bad_modifiers |= true;
2808-
} else {
2809-
info.bad_ref_pats |= true;
2812+
if !from_expansion {
2813+
// Add a secondary label covering the whole pattern noting the default binding mode
2814+
let def_br_desc = match def_br_mutbl {
2815+
Mutability::Not => "default binding mode is `ref`",
2816+
Mutability::Mut => "default binding mode is `ref mut`",
2817+
};
2818+
info.span_labels.push((subpat.span, def_br_desc.to_owned()));
28102819
}
28112820
}
28122821
}

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/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ error: binding modifiers may only be written when the default binding mode is `m
1414
--> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
1515
|
1616
LL | let [ref mut x] = &[0];
17-
| ^^^^^^^ default binding mode is `ref`
17+
| ^^^^^^^--
18+
| |
19+
| this binding modifier
20+
| default binding mode is `ref`
1821
|
1922
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
2023
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
3235
--> $DIR/ref-binding-on-inh-ref-errors.rs:75:10
3336
|
3437
LL | let [ref x] = &[0];
35-
| ^^^ default binding mode is `ref`
38+
| ^^^--
39+
| |
40+
| this binding modifier
41+
| default binding mode is `ref`
3642
|
3743
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
3844
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
4450
--> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
4551
|
4652
LL | let [ref x] = &mut [0];
47-
| ^^^ default binding mode is `ref mut`
53+
| ^^^--
54+
| |
55+
| this binding modifier
56+
| default binding mode is `ref mut`
4857
|
4958
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
5059
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
5665
--> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
5766
|
5867
LL | let [ref mut x] = &mut [0];
59-
| ^^^^^^^ default binding mode is `ref mut`
68+
| ^^^^^^^--
69+
| |
70+
| this binding modifier
71+
| default binding mode is `ref mut`
6072
|
6173
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
6274
help: make the implied reference pattern explicit

tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr

Lines changed: 44 additions & 11 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/ref-binding-on-inh-ref-errors.rs:15:11
33
|
44
LL | let [&ref x] = &[&0];
5-
| ^^^ default binding mode is `ref`
5+
| ^^^--
6+
| |
7+
| this binding modifier
8+
| default binding mode is `ref`
69
|
710
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
811
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
1417
--> $DIR/ref-binding-on-inh-ref-errors.rs:20:11
1518
|
1619
LL | let [&ref x] = &mut [&0];
17-
| ^^^ default binding mode is `ref`
20+
| ^^^--
21+
| |
22+
| this binding modifier
23+
| default binding mode is `ref`
1824
|
1925
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
2026
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
2632
--> $DIR/ref-binding-on-inh-ref-errors.rs:25:15
2733
|
2834
LL | let [&mut ref x] = &mut [&mut 0];
29-
| ^^^ default binding mode is `ref mut`
35+
| ^^^--
36+
| |
37+
| this binding modifier
38+
| default binding mode is `ref mut`
3039
|
3140
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
3241
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
3847
--> $DIR/ref-binding-on-inh-ref-errors.rs:30:15
3948
|
4049
LL | let [&mut ref mut x] = &mut [&mut 0];
41-
| ^^^^^^^ default binding mode is `ref mut`
50+
| ^^^^^^^--
51+
| |
52+
| this binding modifier
53+
| default binding mode is `ref mut`
4254
|
4355
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
4456
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
5062
--> $DIR/ref-binding-on-inh-ref-errors.rs:39:11
5163
|
5264
LL | let [&ref x] = &[&mut 0];
53-
| ^^^ default binding mode is `ref`
65+
| ^^^--
66+
| |
67+
| this binding modifier
68+
| default binding mode is `ref`
5469
|
5570
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
5671
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
6277
--> $DIR/ref-binding-on-inh-ref-errors.rs:45:11
6378
|
6479
LL | let [&ref x] = &mut [&mut 0];
65-
| ^^^ default binding mode is `ref`
80+
| ^^^--
81+
| |
82+
| this binding modifier
83+
| default binding mode is `ref`
6684
|
6785
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
6886
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
7492
--> $DIR/ref-binding-on-inh-ref-errors.rs:54:15
7593
|
7694
LL | let [&mut ref x] = &[&mut 0];
77-
| ^^^ default binding mode is `ref`
95+
| ^^^--
96+
| |
97+
| this binding modifier
98+
| default binding mode is `ref`
7899
|
79100
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
80101
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
86107
--> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
87108
|
88109
LL | let [ref mut x] = &[0];
89-
| ^^^^^^^ default binding mode is `ref`
110+
| ^^^^^^^--
111+
| |
112+
| this binding modifier
113+
| default binding mode is `ref`
90114
|
91115
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
92116
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
104128
--> $DIR/ref-binding-on-inh-ref-errors.rs:75:10
105129
|
106130
LL | let [ref x] = &[0];
107-
| ^^^ default binding mode is `ref`
131+
| ^^^--
132+
| |
133+
| this binding modifier
134+
| default binding mode is `ref`
108135
|
109136
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
110137
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
116143
--> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
117144
|
118145
LL | let [ref x] = &mut [0];
119-
| ^^^ default binding mode is `ref mut`
146+
| ^^^--
147+
| |
148+
| this binding modifier
149+
| default binding mode is `ref mut`
120150
|
121151
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
122152
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
128158
--> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
129159
|
130160
LL | let [ref mut x] = &mut [0];
131-
| ^^^^^^^ default binding mode is `ref mut`
161+
| ^^^^^^^--
162+
| |
163+
| this binding modifier
164+
| default binding mode is `ref mut`
132165
|
133166
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
134167
help: make the implied reference pattern explicit

0 commit comments

Comments
 (0)