From 97cf1c87bd98c13f4de91f7afbc971dba829ac92 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 27 Oct 2023 15:14:55 -0700 Subject: [PATCH] Suggest `=>` --> `>=` in conditions --- .../rustc_parse/src/parser/diagnostics.rs | 20 ++++ compiler/rustc_parse/src/parser/expr.rs | 10 ++ tests/ui/missing/missing-block-hint.stderr | 4 + tests/ui/parser/eq-gt-to-gt-eq.fixed | 45 ++++++++ tests/ui/parser/eq-gt-to-gt-eq.rs | 45 ++++++++ tests/ui/parser/eq-gt-to-gt-eq.stderr | 106 ++++++++++++++++++ 6 files changed, 230 insertions(+) create mode 100644 tests/ui/parser/eq-gt-to-gt-eq.fixed create mode 100644 tests/ui/parser/eq-gt-to-gt-eq.rs create mode 100644 tests/ui/parser/eq-gt-to-gt-eq.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 2a8eb6edd23..8803b243aa8 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -610,6 +610,26 @@ fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool { // 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::Operator | TokenType::Token(TokenKind::Le))) + && !expected.iter().any(|tok| { + matches!( + tok, + TokenType::Token(TokenKind::FatArrow) | TokenType::Token(TokenKind::Comma) + ) + }) + { + err.span_suggestion( + self.token.span, + "you might have meant to write a \"greater than or equal to\" comparison", + ">=", + Applicability::MaybeIncorrect, + ); + } + 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 235b28b6e26..f6678298e5d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2432,6 +2432,7 @@ fn parse_if_after_cond(&mut self, lo: Span, mut cond: P) -> PResult<'a, P< } } 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 { @@ -2456,6 +2457,15 @@ fn parse_if_after_cond(&mut self, lo: Span, mut cond: P) -> PResult<'a, P< "you likely meant to continue parsing the let-chain starting here", ); } else { + // Look for usages of '=>' where '>=' might be intended + if maybe_fatarrow.kind == token::FatArrow { + err.span_suggestion( + maybe_fatarrow.span, + "you might have meant to write a \"greater than or equal to\" comparison", + ">=", + Applicability::MaybeIncorrect, + ); + } err.span_note( cond_span, "the `if` expression is missing a block after this condition", diff --git a/tests/ui/missing/missing-block-hint.stderr b/tests/ui/missing/missing-block-hint.stderr index 16954223a45..18719289abd 100644 --- a/tests/ui/missing/missing-block-hint.stderr +++ b/tests/ui/missing/missing-block-hint.stderr @@ -9,6 +9,10 @@ note: the `if` expression is missing a block after this condition | LL | if (foo) => {} | ^^^^^ +help: you might have meant to write a "greater than or equal to" comparison + | +LL | if (foo) >= {} + | ~~ error: expected `{`, found `bar` --> $DIR/missing-block-hint.rs:7:13 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 00000000000..44cb464fc0c --- /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 00000000000..dca67c89cc0 --- /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 00000000000..73f465f7b9b --- /dev/null +++ b/tests/ui/parser/eq-gt-to-gt-eq.stderr @@ -0,0 +1,106 @@ +error: expected `{`, found `=>` + --> $DIR/eq-gt-to-gt-eq.rs:8:10 + | +LL | if a => b {} + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/eq-gt-to-gt-eq.rs:8:8 + | +LL | if a => b {} + | ^ +help: you might have 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 `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/eq-gt-to-gt-eq.rs:13:8 + | +LL | if a => 1 {} + | ^ +help: you might have 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 `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/eq-gt-to-gt-eq.rs:18:8 + | +LL | if 1 => a {} + | ^ +help: you might have 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 `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/eq-gt-to-gt-eq.rs:24:8 + | +LL | if a => b && a != b {} + | ^ +help: you might have 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 `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/eq-gt-to-gt-eq.rs:30:8 + | +LL | if a != b && a => b {} + | ^^^^^^^^^^^ +help: you might have 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 + | +help: you might have meant to write a "greater than or equal to" comparison + | +LL | let _ = a >= b; + | ~~ + +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 + | +help: you might have meant to write a "greater than or equal to" comparison + | +LL | match a >= b { + | ~~ + +error: aborting due to 7 previous errors +