]> git.lizzy.rs Git - rust.git/commitdiff
implement recovery in check_assoc_op
authorMazdak Farrokhzad <twingoow@gmail.com>
Tue, 3 Dec 2019 09:19:58 +0000 (10:19 +0100)
committerMazdak Farrokhzad <twingoow@gmail.com>
Fri, 20 Dec 2019 21:41:28 +0000 (22:41 +0100)
src/librustc_parse/parser/diagnostics.rs
src/librustc_parse/parser/expr.rs
src/librustc_parse/parser/stmt.rs
src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs
src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr

index ba125cacab48b78a79a7c4e4178dd89cd90d133e..8b58fb03bf4374db62d5bfc0f4560ef069a6aa5a 100644 (file)
@@ -11,7 +11,7 @@
 use syntax::ThinVec;
 use syntax::util::parser::AssocOp;
 use syntax::struct_span_err;
-use syntax_pos::symbol::{kw, sym};
+use syntax_pos::symbol::kw;
 use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError};
 
 use log::{debug, trace};
@@ -312,22 +312,6 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
         };
         self.last_unexpected_token_span = Some(self.token.span);
         let mut err = self.fatal(&msg_exp);
-        if self.token.is_ident_named(sym::and) {
-            err.span_suggestion_short(
-                self.token.span,
-                "use `&&` instead of `and` for the boolean operator",
-                "&&".to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        }
-        if self.token.is_ident_named(sym::or) {
-            err.span_suggestion_short(
-                self.token.span,
-                "use `||` instead of `or` for the boolean operator",
-                "||".to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        }
         let sp = if self.token == token::Eof {
             // This is EOF; don't want to point at the following char, but rather the last token.
             self.prev_span
index f20d0aa2236376acdfecd01685fe9c9f2ef87306..0792f1b3b7f646cd8925b7ca3f7a8ced94aef328 100644 (file)
@@ -345,7 +345,31 @@ fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
     ///
     /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
     fn check_assoc_op(&self) -> Option<AssocOp> {
-        AssocOp::from_token(&self.token)
+        match (AssocOp::from_token(&self.token), &self.token.kind) {
+            (op @ Some(_), _) => op,
+            (None, token::Ident(sym::and, false)) => {
+                self.error_bad_logical_op("and", "&&", "conjunction");
+                Some(AssocOp::LAnd)
+            }
+            (None, token::Ident(sym::or, false)) => {
+                self.error_bad_logical_op("or", "||", "disjunction");
+                Some(AssocOp::LOr)
+            }
+            _ => None,
+        }
+    }
+
+    /// Error on `and` and `or` suggesting `&&` and `||` respectively.
+    fn error_bad_logical_op(&self, bad: &str, good: &str, english: &str) {
+        self.struct_span_err(self.token.span, &format!("`{}` is not a logical operator", bad))
+            .span_suggestion(
+                self.token.span,
+                &format!("instead of `{}`, use `{}` to perform logical {}", bad, good, english),
+                good.to_string(),
+                Applicability::MachineApplicable,
+            )
+            .note("unlike in e.g., python and PHP, `&&` and `||` are used for logical operators")
+            .emit();
     }
 
     /// Checks if this expression is a successfully parsed statement.
index d1ed6968fb93265f9cd6a33f9d625f30ca434593..036badfe75d9fdd18af9c9b0a089a195d3115e50 100644 (file)
@@ -15,7 +15,7 @@
 use syntax::util::classify;
 use syntax::token;
 use syntax_pos::source_map::{respan, Span};
-use syntax_pos::symbol::{kw, sym};
+use syntax_pos::symbol::kw;
 
 use std::mem;
 
@@ -301,25 +301,7 @@ fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
         let sp = self.token.span;
         let tok = self.this_token_descr();
         let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok));
-        let do_not_suggest_help =
-            self.token.is_keyword(kw::In) || self.token == token::Colon;
-
-        if self.token.is_ident_named(sym::and) {
-            e.span_suggestion_short(
-                self.token.span,
-                "use `&&` instead of `and` for the boolean operator",
-                "&&".to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        }
-        if self.token.is_ident_named(sym::or) {
-            e.span_suggestion_short(
-                self.token.span,
-                "use `||` instead of `or` for the boolean operator",
-                "||".to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        }
+        let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon;
 
         // Check to see if the user has written something like
         //
index 687479bad3ffc67d77562fde9588df116f901854..44421b077fa26eb2c0e75f664c07be4d45cbd76f 100644 (file)
@@ -1,17 +1,25 @@
+fn main() {}
+
 fn test_and() {
     let a = true;
     let b = false;
-    if a and b {
-        //~^ ERROR expected `{`, found `and`
+
+    let _ = a and b; //~ ERROR `and` is not a logical operator
+
+    if a and b { //~ ERROR `and` is not a logical operator
         println!("both");
     }
+
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
 }
 
 fn test_or() {
     let a = true;
     let b = false;
-    if a or b {
-        //~^ ERROR expected `{`, found `or`
+
+    let _ = a or b; //~ ERROR `or` is not a logical operator
+
+    if a or b { //~ ERROR `or` is not a logical operator
         println!("both");
     }
 }
@@ -19,8 +27,7 @@ fn test_or() {
 fn test_and_par() {
     let a = true;
     let b = false;
-    if (a and b) {
-        //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
+    if (a and b) {  //~ ERROR `and` is not a logical operator
         println!("both");
     }
 }
@@ -28,8 +35,7 @@ fn test_and_par() {
 fn test_or_par() {
     let a = true;
     let b = false;
-    if (a or b) {
-        //~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
+    if (a or b) {  //~ ERROR `or` is not a logical operator
         println!("both");
     }
 }
@@ -37,8 +43,7 @@ fn test_or_par() {
 fn test_while_and() {
     let a = true;
     let b = false;
-    while a and b {
-        //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
+    while a and b {  //~ ERROR `and` is not a logical operator
         println!("both");
     }
 }
@@ -46,11 +51,7 @@ fn test_while_and() {
 fn test_while_or() {
     let a = true;
     let b = false;
-    while a or b {
-        //~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
+    while a or b { //~ ERROR `or` is not a logical operator
         println!("both");
     }
 }
-
-fn main() {
-}
index f230395f7a51b5362288d2f5345617fa22afa3ce..62c6204fb6f6f8e5ba7c4307873183116f6d9a5f 100644 (file)
@@ -1,58 +1,75 @@
-error: expected `{`, found `and`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:4:10
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:7:15
+   |
+LL |     let _ = a and b;
+   |               ^^^ help: instead of `and`, use `&&` to perform logical conjunction: `&&`
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:9:10
    |
 LL |     if a and b {
-   |     --   ^^^
-   |     |    |
-   |     |    expected `{`
-   |     |    help: use `&&` instead of `and` for the boolean operator
-   |     this `if` statement has a condition, but no block
+   |          ^^^ help: instead of `and`, use `&&` to perform logical conjunction: `&&`
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:20:15
+   |
+LL |     let _ = a or b;
+   |               ^^ help: instead of `or`, use `||` to perform logical disjunction: `||`
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected `{`, found `or`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:13:10
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:10
    |
 LL |     if a or b {
-   |     --   ^^
-   |     |    |
-   |     |    expected `{`
-   |     |    help: use `||` instead of `or` for the boolean operator
-   |     this `if` statement has a condition, but no block
+   |          ^^ help: instead of `or`, use `||` to perform logical disjunction: `||`
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:11
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:30:11
    |
 LL |     if (a and b) {
-   |           ^^^
-   |           |
-   |           expected one of 8 possible tokens
-   |           help: use `&&` instead of `and` for the boolean operator
+   |           ^^^ help: instead of `and`, use `&&` to perform logical conjunction: `&&`
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:31:11
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:38:11
    |
 LL |     if (a or b) {
-   |           ^^
-   |           |
-   |           expected one of 8 possible tokens
-   |           help: use `||` instead of `or` for the boolean operator
+   |           ^^ help: instead of `or`, use `||` to perform logical disjunction: `||`
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:40:13
+error: `and` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:46:13
    |
 LL |     while a and b {
-   |             ^^^
-   |             |
-   |             expected one of `!`, `.`, `::`, `?`, `{`, or an operator
-   |             help: use `&&` instead of `and` for the boolean operator
+   |             ^^^ help: instead of `and`, use `&&` to perform logical conjunction: `&&`
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
 
-error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
-  --> $DIR/issue-54109-and_instead_of_ampersands.rs:49:13
+error: `or` is not a logical operator
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:54:13
    |
 LL |     while a or b {
-   |             ^^
-   |             |
-   |             expected one of `!`, `.`, `::`, `?`, `{`, or an operator
-   |             help: use `||` instead of `or` for the boolean operator
+   |             ^^ help: instead of `or`, use `||` to perform logical disjunction: `||`
+   |
+   = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54109-and_instead_of_ampersands.rs:13:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
 
-error: aborting due to 6 previous errors
+error: aborting due to 9 previous errors
 
+For more information about this error, try `rustc --explain E0308`.