implement recovery in check_assoc_op

This commit is contained in:
Mazdak Farrokhzad 2019-12-03 10:19:58 +01:00
parent 903c9dfd18
commit 52acaa6974
5 changed files with 100 additions and 92 deletions

View File

@ -11,7 +11,7 @@ use syntax::ptr::P;
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 @@ impl<'a> Parser<'a> {
};
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

View File

@ -345,7 +345,31 @@ impl<'a> Parser<'a> {
///
/// 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.

View File

@ -15,7 +15,7 @@ use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac};
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 @@ impl<'a> Parser<'a> {
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
//

View 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() {
}

View 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: 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: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: `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: aborting due to 6 previous errors
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 9 previous errors
For more information about this error, try `rustc --explain E0308`.