Skip to content

Commit eabe462

Browse files
authored
Rollup merge of #156333 - TaKO8Ki:fix-dotdotdot-rest-pattern-unicode-span, r=Urgau
Avoid invalid spans in dotdotdot rest pattern suggestions Fixes #156316 The parser recovers Unicode confusables such as `···` as `...`, while keeping the original source span over the multibyte characters. `recover_dotdotdot_rest_pat` built its suggestion by subtracting `BytePos(1)` from the end of that recovered token span. For multibyte characters, that can create a span boundary inside a UTF-8, causing diagnostic emission to ICE. This changes the suggestion to replace the whole recovered token span with `..` instead of slicing off one byte.
2 parents b2cdfa2 + 431017b commit eabe462

4 files changed

Lines changed: 132 additions & 2 deletions

File tree

compiler/rustc_parse/src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3238,7 +3238,7 @@ pub(crate) struct DotDotDotRestPattern {
32383238
#[suggestion(
32393239
"for a rest pattern, use `..` instead of `...`",
32403240
style = "verbose",
3241-
code = "",
3241+
code = "..",
32423242
applicability = "machine-applicable"
32433243
)]
32443244
pub suggestion: Option<Span>,

compiler/rustc_parse/src/parser/pat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,7 @@ impl<'a> Parser<'a> {
920920
// The user probably mistook `...` for a rest pattern `..`.
921921
self.dcx().emit_err(DotDotDotRestPattern {
922922
span: lo,
923-
suggestion: Some(lo.with_lo(lo.hi() - BytePos(1))),
923+
suggestion: Some(lo),
924924
var_args: None,
925925
});
926926
PatKind::Rest
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Suggestions for `...` in patterns should not perform span manipulations that
2+
// assume the token is ASCII, because it could have been recovered from
3+
// similar-looking Unicode characters.
4+
//
5+
// Regression test for https://github.com/rust-lang/rust/issues/156316.
6+
7+
// These dots are U+00B7 MIDDLE DOT, not ASCII periods.
8+
impl S { fn f(···>) }
9+
//~^ ERROR unknown start of token
10+
//~| ERROR unknown start of token
11+
//~| ERROR unknown start of token
12+
//~| ERROR unexpected `...`
13+
//~| ERROR expected `:`, found `>`
14+
//~| ERROR expected one of
15+
//~| ERROR associated function in `impl` without body
16+
//~| ERROR cannot find type `S` in this scope
17+
//~| ERROR missing pattern for `...` argument
18+
//~| WARN this was previously accepted by the compiler
19+
20+
fn main() {}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
error: unknown start of token: \u{b7}
2+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:15
3+
|
4+
LL | impl S { fn f(···>) }
5+
| ^^^
6+
|
7+
= note: character appears 2 more times
8+
help: Unicode character '·' (Middle Dot) looks like '.' (Period), but it is not
9+
|
10+
LL - impl S { fn f(···>) }
11+
LL + impl S { fn f(...>) }
12+
|
13+
14+
error: unknown start of token: \u{b7}
15+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:16
16+
|
17+
LL | impl S { fn f(···>) }
18+
| ^^
19+
|
20+
= note: character appears once more
21+
help: Unicode character '·' (Middle Dot) looks like '.' (Period), but it is not
22+
|
23+
LL - impl S { fn f(···>) }
24+
LL + impl S { fn f(·..>) }
25+
|
26+
27+
error: unknown start of token: \u{b7}
28+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:17
29+
|
30+
LL | impl S { fn f(···>) }
31+
| ^
32+
|
33+
help: Unicode character '·' (Middle Dot) looks like '.' (Period), but it is not
34+
|
35+
LL - impl S { fn f(···>) }
36+
LL + impl S { fn f(··.>) }
37+
|
38+
39+
error: unexpected `...`
40+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:15
41+
|
42+
LL | impl S { fn f(···>) }
43+
| ^^^ not a valid pattern
44+
|
45+
help: for a rest pattern, use `..` instead of `...`
46+
|
47+
LL - impl S { fn f(···>) }
48+
LL + impl S { fn f(..>) }
49+
|
50+
51+
error: expected `:`, found `>`
52+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:18
53+
|
54+
LL | impl S { fn f(···>) }
55+
| ^ expected `:`
56+
57+
error: expected one of `->`, `where`, or `{`, found `}`
58+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:21
59+
|
60+
LL | impl S { fn f(···>) }
61+
| - ^ expected one of `->`, `where`, or `{`
62+
| |
63+
| while parsing this `fn`
64+
65+
error: associated function in `impl` without body
66+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:10
67+
|
68+
LL | impl S { fn f(···>) }
69+
| ^^^^^^^^^^- help: provide a definition for the function: `{ <body> }`
70+
71+
error[E0425]: cannot find type `S` in this scope
72+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:6
73+
|
74+
LL | impl S { fn f(···>) }
75+
| ^ not found in this scope
76+
77+
error: missing pattern for `...` argument
78+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:15
79+
|
80+
LL | impl S { fn f(···>) }
81+
| ^^^
82+
|
83+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
84+
= note: for more information, see issue #145544 <https://github.com/rust-lang/rust/issues/145544>
85+
= note: `#[deny(varargs_without_pattern)]` (part of `#[deny(future_incompatible)]`) on by default
86+
help: name the argument, or use `_` to continue ignoring it
87+
|
88+
LL - impl S { fn f(···>) }
89+
LL + impl S { fn f(_: ...>) }
90+
|
91+
92+
error: aborting due to 9 previous errors
93+
94+
For more information about this error, try `rustc --explain E0425`.
95+
Future incompatibility report: Future breakage diagnostic:
96+
error: missing pattern for `...` argument
97+
--> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:15
98+
|
99+
LL | impl S { fn f(···>) }
100+
| ^^^
101+
|
102+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
103+
= note: for more information, see issue #145544 <https://github.com/rust-lang/rust/issues/145544>
104+
= note: `#[deny(varargs_without_pattern)]` (part of `#[deny(future_incompatible)]`) on by default
105+
help: name the argument, or use `_` to continue ignoring it
106+
|
107+
LL - impl S { fn f(···>) }
108+
LL + impl S { fn f(_: ...>) }
109+
|
110+

0 commit comments

Comments
 (0)