Skip to content

Commit 72ccf9b

Browse files
Rollup merge of #163106 - Albab-Hasan:const-pattern-note-raw-idents, r=oli-obk
emit the constant pattern note for raw identifier bindings `is_const_pat_that_looks_like_binding` matched the pattern snippet against a plain identifier so the `#` in `let r#x = 0` rejected it and the binding lost both the label pointing at `const x` and the `introduce a variable instead` suggestion. strip a leading `r#` before the check and render the const name with `to_ident_string` in the label so a keyword name prints as `r#fn`. fixes #162949 r? @oli-obk
2 parents 3a7b5aa + 5e86855 commit 72ccf9b

3 files changed

Lines changed: 67 additions & 10 deletions

File tree

‎compiler/rustc_mir_build/src/thir/pattern/check_match.rs‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -678,10 +678,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
678678

679679
if let Some(def_id) = is_const_pat_that_looks_like_binding(self.tcx, pat) {
680680
let span = self.tcx.def_span(def_id);
681-
let variable = self.tcx.item_name(def_id).to_string();
681+
let name = self.tcx.item_name(def_id);
682682
// When we encounter a constant as the binding name, point at the `const` definition.
683-
interpreted_as_const = Some(InterpretedAsConst { span, variable: variable.clone() });
684-
interpreted_as_const_sugg = Some(InterpretedAsConstSugg { span: pat.span, variable });
683+
interpreted_as_const =
684+
Some(InterpretedAsConst { span, variable: name.to_ident_string() });
685+
// The suggested name is suffixed, so it is never a keyword and never needs `r#`.
686+
interpreted_as_const_sugg =
687+
Some(InterpretedAsConstSugg { span: pat.span, variable: name.to_string() });
685688
} else if let PatKind::Constant { .. } = pat.kind
686689
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
687690
{
@@ -1231,7 +1234,11 @@ fn is_const_pat_that_looks_like_binding<'tcx>(tcx: TyCtxt<'tcx>, pat: &Pat<'tcx>
12311234
// `::` namespace separators or other non-identifier characters.
12321235
if let ty::AliasConstKind::Free { def_id } = pat.extra.as_deref()?.expanded_const?
12331236
&& let Ok(snippet) = tcx.sess.source_map().span_to_snippet(pat.span)
1234-
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
1237+
&& snippet
1238+
.strip_prefix("r#")
1239+
.unwrap_or(&snippet)
1240+
.chars()
1241+
.all(|c| c.is_alphanumeric() || c == '_')
12351242
{
12361243
Some(def_id)
12371244
} else {

‎tests/ui/consts/const-pattern-irrefutable.rs‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ use foo::d;
1313
const a: u8 = 2;
1414
//~^ NOTE missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
1515

16+
const g: u8 = 2;
17+
//~^ NOTE missing patterns are not covered because `g` is interpreted as a constant pattern, not a new variable
18+
19+
const r#fn: u8 = 2;
20+
//~^ NOTE missing patterns are not covered because `r#fn` is interpreted as a constant pattern, not a new variable
21+
1622
#[derive(PartialEq)]
1723
struct S {
1824
foo: u8,
@@ -41,5 +47,13 @@ fn main() {
4147
//~| HELP introduce a variable instead
4248
foo: 1,
4349
};
50+
let r#g = 4;
51+
//~^ ERROR refutable pattern in local binding
52+
//~| NOTE patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
53+
//~| HELP introduce a variable instead
54+
let r#fn = 4;
55+
//~^ ERROR refutable pattern in local binding
56+
//~| NOTE patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
57+
//~| HELP introduce a variable instead
4458
fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
4559
}

‎tests/ui/consts/const-pattern-irrefutable.stderr‎

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0005]: refutable pattern in local binding
2-
--> $DIR/const-pattern-irrefutable.rs:26:9
2+
--> $DIR/const-pattern-irrefutable.rs:32:9
33
|
44
LL | const a: u8 = 2;
55
| ----------- missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
@@ -16,7 +16,7 @@ LL | let a_var = 4;
1616
| ++++
1717

1818
error[E0005]: refutable pattern in local binding
19-
--> $DIR/const-pattern-irrefutable.rs:30:9
19+
--> $DIR/const-pattern-irrefutable.rs:36:9
2020
|
2121
LL | pub const b: u8 = 2;
2222
| --------------- missing patterns are not covered because `b` is interpreted as a constant pattern, not a new variable
@@ -34,7 +34,7 @@ LL + let b_var = 4;
3434
|
3535

3636
error[E0005]: refutable pattern in local binding
37-
--> $DIR/const-pattern-irrefutable.rs:34:9
37+
--> $DIR/const-pattern-irrefutable.rs:40:9
3838
|
3939
LL | pub const d: (u8, u8) = (2, 1);
4040
| --------------------- missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
@@ -51,7 +51,7 @@ LL | let d_var = (4, 4);
5151
| ++++
5252

5353
error[E0005]: refutable pattern in local binding
54-
--> $DIR/const-pattern-irrefutable.rs:38:9
54+
--> $DIR/const-pattern-irrefutable.rs:44:9
5555
|
5656
LL | const e: S = S {
5757
| ---------- missing patterns are not covered because `e` is interpreted as a constant pattern, not a new variable
@@ -62,7 +62,7 @@ LL | let e = S {
6262
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
6363
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
6464
note: `S` defined here
65-
--> $DIR/const-pattern-irrefutable.rs:17:8
65+
--> $DIR/const-pattern-irrefutable.rs:23:8
6666
|
6767
LL | struct S {
6868
| ^
@@ -72,6 +72,42 @@ help: introduce a variable instead
7272
LL | let e_var = S {
7373
| ++++
7474

75-
error: aborting due to 4 previous errors
75+
error[E0005]: refutable pattern in local binding
76+
--> $DIR/const-pattern-irrefutable.rs:50:9
77+
|
78+
LL | const g: u8 = 2;
79+
| ----------- missing patterns are not covered because `g` is interpreted as a constant pattern, not a new variable
80+
...
81+
LL | let r#g = 4;
82+
| ^^^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
83+
|
84+
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
85+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
86+
= note: the matched value is of type `u8`
87+
help: introduce a variable instead
88+
|
89+
LL - let r#g = 4;
90+
LL + let g_var = 4;
91+
|
92+
93+
error[E0005]: refutable pattern in local binding
94+
--> $DIR/const-pattern-irrefutable.rs:54:9
95+
|
96+
LL | const r#fn: u8 = 2;
97+
| -------------- missing patterns are not covered because `r#fn` is interpreted as a constant pattern, not a new variable
98+
...
99+
LL | let r#fn = 4;
100+
| ^^^^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
101+
|
102+
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
103+
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
104+
= note: the matched value is of type `u8`
105+
help: introduce a variable instead
106+
|
107+
LL - let r#fn = 4;
108+
LL + let fn_var = 4;
109+
|
110+
111+
error: aborting due to 6 previous errors
76112

77113
For more information about this error, try `rustc --explain E0005`.

0 commit comments

Comments
 (0)