diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index bc17754c56ae3..f74df3d9746ae 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -153,3 +153,6 @@ parser_left_arrow_operator = unexpected token: `<-` parser_remove_let = expected pattern, found `let` .suggestion = remove the unnecessary `let` keyword + +parser_use_eq_instead = unexpected `==` + .suggestion = try using `=` instead diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ad49227222b2c..be524db785bc0 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -713,6 +713,14 @@ pub(crate) struct RemoveLet { pub span: Span, } +#[derive(SessionDiagnostic)] +#[diag(parser::use_eq_instead)] +pub(crate) struct UseEqInstead { + #[primary_span] + #[suggestion_short(applicability = "machine-applicable", code = "=")] + pub span: Span, +} + // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. @@ -957,6 +965,14 @@ impl<'a> Parser<'a> { } } + if self.token.kind == TokenKind::EqEq + && self.prev_token.is_ident() + && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq))) + { + // Likely typo: `=` → `==` in let expr or enum item + return Err(self.sess.create_err(UseEqInstead { span: self.token.span })); + } + let expect = tokens_to_string(&expected); let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { diff --git a/src/test/ui/parser/issue-101477-enum.fixed b/src/test/ui/parser/issue-101477-enum.fixed new file mode 100644 index 0000000000000..1dfeae22aea2f --- /dev/null +++ b/src/test/ui/parser/issue-101477-enum.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +#[allow(dead_code)] +enum Demo { + A = 1, + B = 2 //~ ERROR unexpected `==` + //~^ expected item, found `==` +} + +fn main() {} diff --git a/src/test/ui/parser/issue-101477-enum.rs b/src/test/ui/parser/issue-101477-enum.rs new file mode 100644 index 0000000000000..ea7051d69a4c7 --- /dev/null +++ b/src/test/ui/parser/issue-101477-enum.rs @@ -0,0 +1,10 @@ +// run-rustfix + +#[allow(dead_code)] +enum Demo { + A = 1, + B == 2 //~ ERROR unexpected `==` + //~^ expected item, found `==` +} + +fn main() {} diff --git a/src/test/ui/parser/issue-101477-enum.stderr b/src/test/ui/parser/issue-101477-enum.stderr new file mode 100644 index 0000000000000..bffc881bdc84b --- /dev/null +++ b/src/test/ui/parser/issue-101477-enum.stderr @@ -0,0 +1,14 @@ +error: unexpected `==` + --> $DIR/issue-101477-enum.rs:6:7 + | +LL | B == 2 + | ^^ help: try using `=` instead + +error: expected item, found `==` + --> $DIR/issue-101477-enum.rs:6:7 + | +LL | B == 2 + | ^^ expected item + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/issue-101477-let.fixed b/src/test/ui/parser/issue-101477-let.fixed new file mode 100644 index 0000000000000..9989ad81524e1 --- /dev/null +++ b/src/test/ui/parser/issue-101477-let.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let x = 2; //~ ERROR unexpected `==` + println!("x: {}", x) +} diff --git a/src/test/ui/parser/issue-101477-let.rs b/src/test/ui/parser/issue-101477-let.rs new file mode 100644 index 0000000000000..8b0e8bee1799d --- /dev/null +++ b/src/test/ui/parser/issue-101477-let.rs @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let x == 2; //~ ERROR unexpected `==` + println!("x: {}", x) +} diff --git a/src/test/ui/parser/issue-101477-let.stderr b/src/test/ui/parser/issue-101477-let.stderr new file mode 100644 index 0000000000000..1b30d4b17861a --- /dev/null +++ b/src/test/ui/parser/issue-101477-let.stderr @@ -0,0 +1,8 @@ +error: unexpected `==` + --> $DIR/issue-101477-let.rs:4:11 + | +LL | let x == 2; + | ^^ help: try using `=` instead + +error: aborting due to previous error +