Change:
Right now the raw ident suggestion when using a reserved keyword somewhere where it is not allowed is context free, leading to misleading output: The parser should perform some lookahead to see if it could actually continue parsing if a raw identifier had been supplied in its place and if so, only then suggest raw idents.
Or we shouldn't suggest using raw identifiers if we cannot do that easily and reliably.

Discussion:
self.token.span, &format!("expected identifier, found {}", self.this_token_descr()), ); <ins> let valid_follow = &[ TokenKind::Eq, TokenKind::Colon, TokenKind::Comma, TokenKind::Semi, TokenKind::ModSep, TokenKind::OpenDelim(token::DelimToken::Brace), TokenKind::OpenDelim(token::DelimToken::Paren), TokenKind::CloseDelim(token::DelimToken::Brace), TokenKind::CloseDelim(token::DelimToken::Paren), ]; </ins> if let token::Ident(name, false) = self.token.kind { <del> if Ident::new(name, self.token.span).is_raw_guess() { </del> <ins> if Ident::new(name, self.token.span).is_raw_guess() && self.look_ahead(1, |t| valid_follow.contains(&t.kind)) { </ins> err.span_suggestion( self.token.span, "you can escape reserved keywords to use them as identifiers",

if i > 0 { result.push_str("::"); } <ins> if Ident::with_dummy_span(*name).is_raw_guess() { result.push_str("r#"); } </ins> result.push_str(&name.as_str()); } result } fn path_names_to_string(path: &Path) -> String { <del> names_to_string(&path.segments.iter() .map(|seg| seg.ident.name) .collect::<Vec<_>>()) </del> <ins> names_to_string(&path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>()) </ins> } /// A somewhat inefficient routine to obtain the name of a module.

| LL | pub const async fn x() {} |           ^^^^^ expected identifier, found keyword <del> | help: you can escape reserved keywords to use them as identifiers | LL | pub const r#async fn x() {} |           ^^^^^^^ </del> error: expected `:`, found keyword `fn` --> $DIR/no-const-async.rs:5:17

| LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A) |                     ^^^ expected identifier, found keyword <del> | help: you can escape reserved keywords to use them as identifiers | LL | fn foo2<I>(x: <I as r#for<'x> Foo<&'x isize>>::A) |                     ^^^^^ </del> error: expected one of `::` or `>`, found `Foo` --> $DIR/associated-types-project-from-hrtb-explicit.rs:10:29

| LL | trait T { | ^^^^^ expected identifier, found keyword <del> | help: you can escape reserved keywords to use them as identifiers | LL | r#trait T { | ^^^^^^^ </del> error: expected `:`, found `T` --> $DIR/missing-close-brace-in-struct.rs:4:7

| LL |     let foo: (), |     ^^^ expected identifier, found keyword <del> | help: you can escape reserved keywords to use them as identifiers | LL |     r#let foo: (), |     ^^^^^ </del> error: expected `:`, found `foo` --> $DIR/removed-syntax-field-let.rs:2:9

| LL | use std::any:: as foo; |                ^^ expected identifier, found keyword <del> | help: you can escape reserved keywords to use them as identifiers | LL | use std::any:: r#as foo; |                ^^^^ </del> error: expected one of `::`, `;`, or `as`, found `foo` --> $DIR/use-as-where-use-ends-with-mod-sep.rs:1:19

<ins> mod foo { pub fn r#let() {} pub fn break() {} //~ ERROR expected identifier, found keyword `break` } fn main() { foo::let(); //~ ERROR expected identifier, found keyword `let` r#break(); //~ ERROR cannot find function `break` in this scope } </ins>

<ins> error: expected identifier, found keyword `break` --> $DIR/raw-name-use-suggestion.rs:3:12 | LL |     pub fn break() {} |            ^^^^^ expected identifier, found keyword | help: you can escape reserved keywords to use them as identifiers | LL |     pub fn r#break() {} |            ^^^^^^^ error: expected identifier, found keyword `let` --> $DIR/raw-name-use-suggestion.rs:7:10 | LL |     foo::let(); |          ^^^ expected identifier, found keyword | help: you can escape reserved keywords to use them as identifiers | LL |     foo::r#let(); |          ^^^^^ error[E0425]: cannot find function `break` in this scope --> $DIR/raw-name-use-suggestion.rs:8:5 | LL |     r#break(); |     ^^^^^^^ not found in this scope | help: possible candidate is found in another module, you can import it into scope | LL | use foo::r#break; | error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0425`. </ins>

LL | LL |         let x = 5; |         ^^^ expected identifier, found keyword <del> | help: you can escape reserved keywords to use them as identifiers | LL |         r#let x = 5; |         ^^^^^ </del> error[E0574]: expected struct, variant or union type, found macro `try` --> $DIR/try-block-in-edition2015.rs:4:33