Don't emit "is not a logical operator" error outside of associative expressions

Avoid showing this error where it doesn't make sense by not assuming
"and" and "or" were intended to mean "&&" and "||" until after we decide
to continue parsing input as an associative expression.

Note that the decision of whether or not to continue parsing input as an
associative expression doesn't actually depend on this assumption.

Fixes #75599
This commit is contained in:
Tyson Nottingham 2020-08-17 19:15:51 -07:00
parent 792c645ca7
commit ff73a40995
7 changed files with 42 additions and 170 deletions

View file

@ -308,7 +308,7 @@ impl<'a> Parser<'a> {
}
fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
match (self.expr_is_complete(lhs), self.check_assoc_op().map(|op| op.node)) {
match (self.expr_is_complete(lhs), AssocOp::from_token(&self.token)) {
// Semi-statement forms are odd:
// See https://github.com/rust-lang/rust/issues/29071
(true, None) => false,

View file

@ -5,10 +5,8 @@ fn test_and() {
let b = false;
let _ = a and b; //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
if a and b { //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
println!("both");
}
@ -20,10 +18,8 @@ fn test_or() {
let b = false;
let _ = a or b; //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
if a or b { //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
println!("both");
}
}
@ -32,7 +28,6 @@ fn test_and_par() {
let a = true;
let b = false;
if (a and b) { //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
println!("both");
}
}
@ -41,7 +36,6 @@ fn test_or_par() {
let a = true;
let b = false;
if (a or b) { //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
println!("both");
}
}
@ -50,7 +44,6 @@ fn test_while_and() {
let a = true;
let b = false;
while a and b { //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
println!("both");
}
}
@ -59,7 +52,6 @@ fn test_while_or() {
let a = true;
let b = false;
while a or b { //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
println!("both");
}
}

View file

@ -7,23 +7,7 @@ LL | let _ = a and b;
= 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:7:15
|
LL | let _ = a and b;
| ^^^ help: 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:10:10
|
LL | if a and b {
| ^^^ help: 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:10:10
--> $DIR/issue-54109-and_instead_of_ampersands.rs:9:10
|
LL | if a and b {
| ^^^ help: use `&&` to perform logical conjunction
@ -31,7 +15,7 @@ LL | if a and b {
= 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:15
--> $DIR/issue-54109-and_instead_of_ampersands.rs:20:15
|
LL | let _ = a or b;
| ^^ help: use `||` to perform logical disjunction
@ -39,23 +23,7 @@ LL | let _ = a or b;
= 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:15
|
LL | let _ = a or b;
| ^^ help: 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:25:10
|
LL | if a or b {
| ^^ help: 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:25:10
--> $DIR/issue-54109-and_instead_of_ampersands.rs:22:10
|
LL | if a or b {
| ^^ help: use `||` to perform logical disjunction
@ -63,15 +31,7 @@ LL | if a or b {
= 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:34:11
|
LL | if (a and b) {
| ^^^ help: 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:34:11
--> $DIR/issue-54109-and_instead_of_ampersands.rs:30:11
|
LL | if (a and b) {
| ^^^ help: use `&&` to perform logical conjunction
@ -79,15 +39,7 @@ LL | if (a and b) {
= 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:43:11
|
LL | if (a or b) {
| ^^ help: 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:43:11
--> $DIR/issue-54109-and_instead_of_ampersands.rs:38:11
|
LL | if (a or b) {
| ^^ help: use `||` to perform logical disjunction
@ -95,15 +47,7 @@ LL | if (a or b) {
= 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:52:13
|
LL | while a and b {
| ^^^ help: 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:52:13
--> $DIR/issue-54109-and_instead_of_ampersands.rs:46:13
|
LL | while a and b {
| ^^^ help: use `&&` to perform logical conjunction
@ -111,15 +55,7 @@ LL | while a and b {
= 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:61:13
|
LL | while a or b {
| ^^ help: 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:61:13
--> $DIR/issue-54109-and_instead_of_ampersands.rs:54:13
|
LL | while a or b {
| ^^ help: use `||` to perform logical disjunction
@ -127,13 +63,13 @@ LL | while a or b {
= 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:15:33
--> $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 17 previous errors
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -11,10 +11,8 @@ fn test_and() {
let b = false;
let _ = a && b; //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
if a && b { //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
println!("both");
}
}
@ -24,10 +22,8 @@ fn test_or() {
let b = false;
let _ = a || b; //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
if a || b { //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
println!("both");
}
}
@ -36,7 +32,6 @@ fn test_and_par() {
let a = true;
let b = false;
if (a && b) { //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
println!("both");
}
}
@ -45,7 +40,6 @@ fn test_or_par() {
let a = true;
let b = false;
if (a || b) { //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
println!("both");
}
}
@ -54,7 +48,6 @@ fn test_while_and() {
let a = true;
let b = false;
while a && b { //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
println!("both");
}
}
@ -63,7 +56,6 @@ fn test_while_or() {
let a = true;
let b = false;
while a || b { //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
println!("both");
}
}

View file

@ -11,10 +11,8 @@ fn test_and() {
let b = false;
let _ = a and b; //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
if a and b { //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
println!("both");
}
}
@ -24,10 +22,8 @@ fn test_or() {
let b = false;
let _ = a or b; //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
if a or b { //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
println!("both");
}
}
@ -36,7 +32,6 @@ fn test_and_par() {
let a = true;
let b = false;
if (a and b) { //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
println!("both");
}
}
@ -45,7 +40,6 @@ fn test_or_par() {
let a = true;
let b = false;
if (a or b) { //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
println!("both");
}
}
@ -54,7 +48,6 @@ fn test_while_and() {
let a = true;
let b = false;
while a and b { //~ ERROR `and` is not a logical operator
//~| ERROR `and` is not a logical operator
println!("both");
}
}
@ -63,7 +56,6 @@ fn test_while_or() {
let a = true;
let b = false;
while a or b { //~ ERROR `or` is not a logical operator
//~| ERROR `or` is not a logical operator
println!("both");
}
}

View file

@ -7,23 +7,7 @@ LL | let _ = a and b;
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
error: `and` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:13:15
|
LL | let _ = a and b;
| ^^^ help: 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-without-witness.rs:16:10
|
LL | if a and b {
| ^^^ help: 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-without-witness.rs:16:10
--> $DIR/issue-54109-without-witness.rs:15:10
|
LL | if a and b {
| ^^^ help: use `&&` to perform logical conjunction
@ -31,7 +15,7 @@ LL | if a and b {
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:26:15
--> $DIR/issue-54109-without-witness.rs:24:15
|
LL | let _ = a or b;
| ^^ help: use `||` to perform logical disjunction
@ -39,23 +23,7 @@ LL | let _ = a or b;
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:26:15
|
LL | let _ = a or b;
| ^^ help: 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-without-witness.rs:29:10
|
LL | if a or b {
| ^^ help: 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-without-witness.rs:29:10
--> $DIR/issue-54109-without-witness.rs:26:10
|
LL | if a or b {
| ^^ help: use `||` to perform logical disjunction
@ -63,15 +31,7 @@ LL | if a or b {
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
error: `and` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:38:11
|
LL | if (a and b) {
| ^^^ help: 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-without-witness.rs:38:11
--> $DIR/issue-54109-without-witness.rs:34:11
|
LL | if (a and b) {
| ^^^ help: use `&&` to perform logical conjunction
@ -79,15 +39,7 @@ LL | if (a and b) {
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:47:11
|
LL | if (a or b) {
| ^^ help: 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-without-witness.rs:47:11
--> $DIR/issue-54109-without-witness.rs:42:11
|
LL | if (a or b) {
| ^^ help: use `||` to perform logical disjunction
@ -95,15 +47,7 @@ LL | if (a or b) {
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
error: `and` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:56:13
|
LL | while a and b {
| ^^^ help: 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-without-witness.rs:56:13
--> $DIR/issue-54109-without-witness.rs:50:13
|
LL | while a and b {
| ^^^ help: use `&&` to perform logical conjunction
@ -111,20 +55,12 @@ LL | while a and b {
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:65:13
--> $DIR/issue-54109-without-witness.rs:58:13
|
LL | while a or b {
| ^^ help: 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-without-witness.rs:65:13
|
LL | while a or b {
| ^^ help: use `||` to perform logical disjunction
|
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
error: aborting due to 16 previous errors
error: aborting due to 8 previous errors

View file

@ -0,0 +1,24 @@
// check-pass
#![allow(non_upper_case_globals)]
const or: usize = 1;
const and: usize = 2;
mod or {
pub const X: usize = 3;
}
mod and {
pub const X: usize = 4;
}
fn main() {
match 0 {
0 => {}
or => {}
and => {}
or::X => {}
and::X => {}
_ => {}
}
}