Skip to content

Commit 4f25c61

Browse files
committed
Rework raw ident suggestions
Use heuristics to determine whethersuggesting raw identifiers is appropriate. Account for raw identifiers when printing a path in a `use` suggestion.
1 parent f11759d commit 4f25c61

11 files changed

+73
-36
lines changed

src/librustc_parse/parser/diagnostics.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,21 @@ impl<'a> Parser<'a> {
225225
self.token.span,
226226
&format!("expected identifier, found {}", self.this_token_descr()),
227227
);
228+
let valid_follow = &[
229+
TokenKind::Eq,
230+
TokenKind::Colon,
231+
TokenKind::Comma,
232+
TokenKind::Semi,
233+
TokenKind::ModSep,
234+
TokenKind::OpenDelim(token::DelimToken::Brace),
235+
TokenKind::OpenDelim(token::DelimToken::Paren),
236+
TokenKind::CloseDelim(token::DelimToken::Brace),
237+
TokenKind::CloseDelim(token::DelimToken::Paren),
238+
];
228239
if let token::Ident(name, false) = self.token.kind {
229-
if Ident::new(name, self.token.span).is_raw_guess() {
240+
if Ident::new(name, self.token.span).is_raw_guess() &&
241+
self.look_ahead(1, |t| valid_follow.contains(&t.kind))
242+
{
230243
err.span_suggestion(
231244
self.token.span,
232245
"you can escape reserved keywords to use them as identifiers",

src/librustc_resolve/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -2893,15 +2893,16 @@ fn names_to_string(names: &[Name]) -> String {
28932893
if i > 0 {
28942894
result.push_str("::");
28952895
}
2896+
if name.is_used_keyword() && name.can_be_raw() {
2897+
result.push_str("r#");
2898+
}
28962899
result.push_str(&name.as_str());
28972900
}
28982901
result
28992902
}
29002903

29012904
fn path_names_to_string(path: &Path) -> String {
2902-
names_to_string(&path.segments.iter()
2903-
.map(|seg| seg.ident.name)
2904-
.collect::<Vec<_>>())
2905+
names_to_string(&path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>())
29052906
}
29062907

29072908
/// A somewhat inefficient routine to obtain the name of a module.

src/libsyntax_pos/symbol.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,15 @@ pub mod sym {
10131013
}
10141014

10151015
impl Symbol {
1016-
fn is_used_keyword_2018(self) -> bool {
1016+
pub fn is_used_keyword(self) -> bool {
1017+
self.is_used_keyword_2015() || self.is_used_keyword_2018()
1018+
}
1019+
1020+
pub fn is_used_keyword_2015(self) -> bool {
1021+
self >= kw::As && self <= kw::While
1022+
}
1023+
1024+
pub fn is_used_keyword_2018(self) -> bool {
10171025
self >= kw::Async && self <= kw::Dyn
10181026
}
10191027

@@ -1057,7 +1065,7 @@ impl Ident {
10571065
/// Returns `true` if the token is a keyword used in the language.
10581066
pub fn is_used_keyword(self) -> bool {
10591067
// Note: `span.edition()` is relatively expensive, don't call it unless necessary.
1060-
self.name >= kw::As && self.name <= kw::While ||
1068+
self.name.is_used_keyword_2015() ||
10611069
self.name.is_used_keyword_2018() && self.span.rust_2018()
10621070
}
10631071

src/test/ui/async-await/no-const-async.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ error: expected identifier, found keyword `async`
33
|
44
LL | pub const async fn x() {}
55
| ^^^^^ expected identifier, found keyword
6-
|
7-
help: you can escape reserved keywords to use them as identifiers
8-
|
9-
LL | pub const r#async fn x() {}
10-
| ^^^^^^^
116

127
error: expected `:`, found keyword `fn`
138
--> $DIR/no-const-async.rs:5:17

src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ error: expected identifier, found keyword `for`
33
|
44
LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A)
55
| ^^^ expected identifier, found keyword
6-
|
7-
help: you can escape reserved keywords to use them as identifiers
8-
|
9-
LL | fn foo2<I>(x: <I as r#for<'x> Foo<&'x isize>>::A)
10-
| ^^^^^
116

127
error: expected one of `::` or `>`, found `Foo`
138
--> $DIR/associated-types-project-from-hrtb-explicit.rs:10:29

src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ error: expected identifier, found keyword `trait`
1212
|
1313
LL | trait T {
1414
| ^^^^^ expected identifier, found keyword
15-
|
16-
help: you can escape reserved keywords to use them as identifiers
17-
|
18-
LL | r#trait T {
19-
| ^^^^^^^
2015

2116
error: expected `:`, found `T`
2217
--> $DIR/missing-close-brace-in-struct.rs:4:7

src/test/ui/parser/removed-syntax-field-let.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ error: expected identifier, found keyword `let`
33
|
44
LL | let foo: (),
55
| ^^^ expected identifier, found keyword
6-
|
7-
help: you can escape reserved keywords to use them as identifiers
8-
|
9-
LL | r#let foo: (),
10-
| ^^^^^
116

127
error: expected `:`, found `foo`
138
--> $DIR/removed-syntax-field-let.rs:2:9

src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ error: expected identifier, found keyword `as`
33
|
44
LL | use std::any:: as foo;
55
| ^^ expected identifier, found keyword
6-
|
7-
help: you can escape reserved keywords to use them as identifiers
8-
|
9-
LL | use std::any:: r#as foo;
10-
| ^^^^
116

127
error: expected one of `::`, `;`, or `as`, found `foo`
138
--> $DIR/use-as-where-use-ends-with-mod-sep.rs:1:19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
mod foo {
2+
pub fn r#let() {}
3+
pub fn break() {} //~ ERROR expected identifier, found keyword `break`
4+
}
5+
6+
fn main() {
7+
foo::let(); //~ ERROR expected identifier, found keyword `let`
8+
r#break(); //~ ERROR cannot find function `break` in this scope
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error: expected identifier, found keyword `break`
2+
--> $DIR/raw-name-use-suggestion.rs:3:12
3+
|
4+
LL | pub fn break() {}
5+
| ^^^^^ expected identifier, found keyword
6+
|
7+
help: you can escape reserved keywords to use them as identifiers
8+
|
9+
LL | pub fn r#break() {}
10+
| ^^^^^^^
11+
12+
error: expected identifier, found keyword `let`
13+
--> $DIR/raw-name-use-suggestion.rs:7:10
14+
|
15+
LL | foo::let();
16+
| ^^^ expected identifier, found keyword
17+
|
18+
help: you can escape reserved keywords to use them as identifiers
19+
|
20+
LL | foo::r#let();
21+
| ^^^^^
22+
23+
error[E0425]: cannot find function `break` in this scope
24+
--> $DIR/raw-name-use-suggestion.rs:8:5
25+
|
26+
LL | r#break();
27+
| ^^^^^^^ not found in this scope
28+
|
29+
help: possible candidate is found in another module, you can import it into scope
30+
|
31+
LL | use foo::r#break;
32+
|
33+
34+
error: aborting due to 3 previous errors
35+
36+
For more information about this error, try `rustc --explain E0425`.

src/test/ui/try-block/try-block-in-edition2015.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ LL | let try_result: Option<_> = try {
66
LL |
77
LL | let x = 5;
88
| ^^^ expected identifier, found keyword
9-
|
10-
help: you can escape reserved keywords to use them as identifiers
11-
|
12-
LL | r#let x = 5;
13-
| ^^^^^
149

1510
error[E0574]: expected struct, variant or union type, found macro `try`
1611
--> $DIR/try-block-in-edition2015.rs:4:33

0 commit comments

Comments
 (0)