diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 2a8eb6edd23fd..dc46326b82e9c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -610,6 +610,18 @@ impl<'a> Parser<'a> { // FIXME: translation requires list formatting (for `expect`) let mut err = self.struct_span_err(self.token.span, msg_exp); + // Look for usages of '=>' where '>=' was probably intended + if self.token == token::FatArrow + && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Le))) + { + err.span_suggestion( + self.token.span, + "you might have meant to write a \"greater than or equal to\" comparison", + ">=", + Applicability::Unspecified, + ); + } + if let TokenKind::Ident(symbol, _) = &self.prev_token.kind { if ["def", "fun", "func", "function"].contains(&symbol.as_str()) { err.span_suggestion_short( diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 235b28b6e26e2..c6a10af718eb6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2432,6 +2432,7 @@ impl<'a> Parser<'a> { } } else { let attrs = self.parse_outer_attributes()?; // For recovery. + let maybe_fatarrow = self.token.clone(); let block = if self.check(&token::OpenDelim(Delimiter::Brace)) { self.parse_block()? } else { @@ -2455,6 +2456,15 @@ impl<'a> Parser<'a> { self.token.span.to(maybe_let.span), "you likely meant to continue parsing the let-chain starting here", ); + } + // Look for usages of '=>' where '>=' was probably intended + if maybe_fatarrow.kind == token::FatArrow { + err.span_suggestion( + maybe_fatarrow.span, + "you probably meant to write a \"greater than or equal to\" comparison", + ">=", + Applicability::MachineApplicable, + ); } else { err.span_note( cond_span, diff --git a/tests/ui/parser/eq-gt-to-gt-eq.fixed b/tests/ui/parser/eq-gt-to-gt-eq.fixed new file mode 100644 index 0000000000000..f818645532304 --- /dev/null +++ b/tests/ui/parser/eq-gt-to-gt-eq.fixed @@ -0,0 +1,45 @@ +// run-rustfix +// Check that we try to correct `=>` to `>=` in conditions. +#![allow(unused)] + +fn main() { + let a = 0; + let b = 1; + if a >= b {} //~ERROR +} + +fn foo() { + let a = 0; + if a >= 1 {} //~ERROR +} + +fn a() { + let a = 0; + if 1 >= a {} //~ERROR +} + +fn bar() { + let a = 0; + let b = 1; + if a >= b && a != b {} //~ERROR +} + +fn qux() { + let a = 0; + let b = 1; + if a != b && a >= b {} //~ERROR +} + +fn baz() { + let a = 0; + let b = 1; + let _ = a => b; //~ERROR +} + +fn b() { + let a = 0; + let b = 1; + match a => b { //~ERROR + _ => todo!(), + } +} diff --git a/tests/ui/parser/eq-gt-to-gt-eq.rs b/tests/ui/parser/eq-gt-to-gt-eq.rs new file mode 100644 index 0000000000000..dca67c89cc033 --- /dev/null +++ b/tests/ui/parser/eq-gt-to-gt-eq.rs @@ -0,0 +1,45 @@ +// run-rustfix +// Check that we try to correct `=>` to `>=` in conditions. +#![allow(unused)] + +fn main() { + let a = 0; + let b = 1; + if a => b {} //~ERROR +} + +fn foo() { + let a = 0; + if a => 1 {} //~ERROR +} + +fn a() { + let a = 0; + if 1 => a {} //~ERROR +} + +fn bar() { + let a = 0; + let b = 1; + if a => b && a != b {} //~ERROR +} + +fn qux() { + let a = 0; + let b = 1; + if a != b && a => b {} //~ERROR +} + +fn baz() { + let a = 0; + let b = 1; + let _ = a => b; //~ERROR +} + +fn b() { + let a = 0; + let b = 1; + match a => b { //~ERROR + _ => todo!(), + } +} diff --git a/tests/ui/parser/eq-gt-to-gt-eq.stderr b/tests/ui/parser/eq-gt-to-gt-eq.stderr new file mode 100644 index 0000000000000..aaf7ca69053bb --- /dev/null +++ b/tests/ui/parser/eq-gt-to-gt-eq.stderr @@ -0,0 +1,71 @@ +error: expected `{`, found `=>` + --> $DIR/eq-gt-to-gt-eq.rs:8:10 + | +LL | if a => b {} + | ^^ expected `{` + | +help: you probably meant to write a "greater than or equal to" comparison + | +LL | if a >= b {} + | ~~ + +error: expected `{`, found `=>` + --> $DIR/eq-gt-to-gt-eq.rs:13:10 + | +LL | if a => 1 {} + | ^^ expected `{` + | +help: you probably meant to write a "greater than or equal to" comparison + | +LL | if a >= 1 {} + | ~~ + +error: expected `{`, found `=>` + --> $DIR/eq-gt-to-gt-eq.rs:18:10 + | +LL | if 1 => a {} + | ^^ expected `{` + | +help: you probably meant to write a "greater than or equal to" comparison + | +LL | if 1 >= a {} + | ~~ + +error: expected `{`, found `=>` + --> $DIR/eq-gt-to-gt-eq.rs:24:10 + | +LL | if a => b && a != b {} + | ^^ expected `{` + | +help: you probably meant to write a "greater than or equal to" comparison + | +LL | if a >= b && a != b {} + | ~~ + +error: expected `{`, found `=>` + --> $DIR/eq-gt-to-gt-eq.rs:30:20 + | +LL | if a != b && a => b {} + | ^^ expected `{` + | +help: you probably meant to write a "greater than or equal to" comparison + | +LL | if a != b && a >= b {} + | ~~ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `=>` + --> $DIR/eq-gt-to-gt-eq.rs:36:15 + | +LL | let _ = a => b; + | ^^ expected one of 8 possible tokens + +error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `=>` + --> $DIR/eq-gt-to-gt-eq.rs:42:13 + | +LL | match a => b { + | ----- ^^ expected one of `!`, `.`, `::`, `?`, `{`, or an operator + | | + | while parsing this `match` expression + +error: aborting due to 7 previous errors +