Skip to content

Commit 52acaa6

Browse files
committed
implement recovery in check_assoc_op
1 parent 903c9df commit 52acaa6

File tree

5 files changed

+100
-92
lines changed

5 files changed

+100
-92
lines changed

src/librustc_parse/parser/diagnostics.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use syntax::ptr::P;
1111
use syntax::ThinVec;
1212
use syntax::util::parser::AssocOp;
1313
use syntax::struct_span_err;
14-
use syntax_pos::symbol::{kw, sym};
14+
use syntax_pos::symbol::kw;
1515
use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError};
1616

1717
use log::{debug, trace};
@@ -312,22 +312,6 @@ impl<'a> Parser<'a> {
312312
};
313313
self.last_unexpected_token_span = Some(self.token.span);
314314
let mut err = self.fatal(&msg_exp);
315-
if self.token.is_ident_named(sym::and) {
316-
err.span_suggestion_short(
317-
self.token.span,
318-
"use `&&` instead of `and` for the boolean operator",
319-
"&&".to_string(),
320-
Applicability::MaybeIncorrect,
321-
);
322-
}
323-
if self.token.is_ident_named(sym::or) {
324-
err.span_suggestion_short(
325-
self.token.span,
326-
"use `||` instead of `or` for the boolean operator",
327-
"||".to_string(),
328-
Applicability::MaybeIncorrect,
329-
);
330-
}
331315
let sp = if self.token == token::Eof {
332316
// This is EOF; don't want to point at the following char, but rather the last token.
333317
self.prev_span

src/librustc_parse/parser/expr.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,31 @@ impl<'a> Parser<'a> {
345345
///
346346
/// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
347347
fn check_assoc_op(&self) -> Option<AssocOp> {
348-
AssocOp::from_token(&self.token)
348+
match (AssocOp::from_token(&self.token), &self.token.kind) {
349+
(op @ Some(_), _) => op,
350+
(None, token::Ident(sym::and, false)) => {
351+
self.error_bad_logical_op("and", "&&", "conjunction");
352+
Some(AssocOp::LAnd)
353+
}
354+
(None, token::Ident(sym::or, false)) => {
355+
self.error_bad_logical_op("or", "||", "disjunction");
356+
Some(AssocOp::LOr)
357+
}
358+
_ => None,
359+
}
360+
}
361+
362+
/// Error on `and` and `or` suggesting `&&` and `||` respectively.
363+
fn error_bad_logical_op(&self, bad: &str, good: &str, english: &str) {
364+
self.struct_span_err(self.token.span, &format!("`{}` is not a logical operator", bad))
365+
.span_suggestion(
366+
self.token.span,
367+
&format!("instead of `{}`, use `{}` to perform logical {}", bad, good, english),
368+
good.to_string(),
369+
Applicability::MachineApplicable,
370+
)
371+
.note("unlike in e.g., python and PHP, `&&` and `||` are used for logical operators")
372+
.emit();
349373
}
350374

351375
/// Checks if this expression is a successfully parsed statement.

src/librustc_parse/parser/stmt.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac};
1515
use syntax::util::classify;
1616
use syntax::token;
1717
use syntax_pos::source_map::{respan, Span};
18-
use syntax_pos::symbol::{kw, sym};
18+
use syntax_pos::symbol::kw;
1919

2020
use std::mem;
2121

@@ -301,25 +301,7 @@ impl<'a> Parser<'a> {
301301
let sp = self.token.span;
302302
let tok = self.this_token_descr();
303303
let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok));
304-
let do_not_suggest_help =
305-
self.token.is_keyword(kw::In) || self.token == token::Colon;
306-
307-
if self.token.is_ident_named(sym::and) {
308-
e.span_suggestion_short(
309-
self.token.span,
310-
"use `&&` instead of `and` for the boolean operator",
311-
"&&".to_string(),
312-
Applicability::MaybeIncorrect,
313-
);
314-
}
315-
if self.token.is_ident_named(sym::or) {
316-
e.span_suggestion_short(
317-
self.token.span,
318-
"use `||` instead of `or` for the boolean operator",
319-
"||".to_string(),
320-
Applicability::MaybeIncorrect,
321-
);
322-
}
304+
let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon;
323305

324306
// Check to see if the user has written something like
325307
//

src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,57 @@
1+
fn main() {}
2+
13
fn test_and() {
24
let a = true;
35
let b = false;
4-
if a and b {
5-
//~^ ERROR expected `{`, found `and`
6+
7+
let _ = a and b; //~ ERROR `and` is not a logical operator
8+
9+
if a and b { //~ ERROR `and` is not a logical operator
610
println!("both");
711
}
12+
13+
let _recovery_witness: () = 0; //~ ERROR mismatched types
814
}
915

1016
fn test_or() {
1117
let a = true;
1218
let b = false;
13-
if a or b {
14-
//~^ ERROR expected `{`, found `or`
19+
20+
let _ = a or b; //~ ERROR `or` is not a logical operator
21+
22+
if a or b { //~ ERROR `or` is not a logical operator
1523
println!("both");
1624
}
1725
}
1826

1927
fn test_and_par() {
2028
let a = true;
2129
let b = false;
22-
if (a and b) {
23-
//~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
30+
if (a and b) { //~ ERROR `and` is not a logical operator
2431
println!("both");
2532
}
2633
}
2734

2835
fn test_or_par() {
2936
let a = true;
3037
let b = false;
31-
if (a or b) {
32-
//~^ ERROR expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
38+
if (a or b) { //~ ERROR `or` is not a logical operator
3339
println!("both");
3440
}
3541
}
3642

3743
fn test_while_and() {
3844
let a = true;
3945
let b = false;
40-
while a and b {
41-
//~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
46+
while a and b { //~ ERROR `and` is not a logical operator
4247
println!("both");
4348
}
4449
}
4550

4651
fn test_while_or() {
4752
let a = true;
4853
let b = false;
49-
while a or b {
50-
//~^ ERROR expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
54+
while a or b { //~ ERROR `or` is not a logical operator
5155
println!("both");
5256
}
5357
}
54-
55-
fn main() {
56-
}
Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,75 @@
1-
error: expected `{`, found `and`
2-
--> $DIR/issue-54109-and_instead_of_ampersands.rs:4:10
1+
error: `and` is not a logical operator
2+
--> $DIR/issue-54109-and_instead_of_ampersands.rs:7:15
3+
|
4+
LL | let _ = a and b;
5+
| ^^^ help: instead of `and`, use `&&` to perform logical conjunction: `&&`
6+
|
7+
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
8+
9+
error: `and` is not a logical operator
10+
--> $DIR/issue-54109-and_instead_of_ampersands.rs:9:10
311
|
412
LL | if a and b {
5-
| -- ^^^
6-
| | |
7-
| | expected `{`
8-
| | help: use `&&` instead of `and` for the boolean operator
9-
| this `if` statement has a condition, but no block
13+
| ^^^ help: instead of `and`, use `&&` to perform logical conjunction: `&&`
14+
|
15+
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
16+
17+
error: `or` is not a logical operator
18+
--> $DIR/issue-54109-and_instead_of_ampersands.rs:20:15
19+
|
20+
LL | let _ = a or b;
21+
| ^^ help: instead of `or`, use `||` to perform logical disjunction: `||`
22+
|
23+
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
1024

11-
error: expected `{`, found `or`
12-
--> $DIR/issue-54109-and_instead_of_ampersands.rs:13:10
25+
error: `or` is not a logical operator
26+
--> $DIR/issue-54109-and_instead_of_ampersands.rs:22:10
1327
|
1428
LL | if a or b {
15-
| -- ^^
16-
| | |
17-
| | expected `{`
18-
| | help: use `||` instead of `or` for the boolean operator
19-
| this `if` statement has a condition, but no block
29+
| ^^ help: instead of `or`, use `||` to perform logical disjunction: `||`
30+
|
31+
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
2032

21-
error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
22-
--> $DIR/issue-54109-and_instead_of_ampersands.rs:22:11
33+
error: `and` is not a logical operator
34+
--> $DIR/issue-54109-and_instead_of_ampersands.rs:30:11
2335
|
2436
LL | if (a and b) {
25-
| ^^^
26-
| |
27-
| expected one of 8 possible tokens
28-
| help: use `&&` instead of `and` for the boolean operator
37+
| ^^^ help: instead of `and`, use `&&` to perform logical conjunction: `&&`
38+
|
39+
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
2940

30-
error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `or`
31-
--> $DIR/issue-54109-and_instead_of_ampersands.rs:31:11
41+
error: `or` is not a logical operator
42+
--> $DIR/issue-54109-and_instead_of_ampersands.rs:38:11
3243
|
3344
LL | if (a or b) {
34-
| ^^
35-
| |
36-
| expected one of 8 possible tokens
37-
| help: use `||` instead of `or` for the boolean operator
45+
| ^^ help: instead of `or`, use `||` to perform logical disjunction: `||`
46+
|
47+
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
3848

39-
error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `and`
40-
--> $DIR/issue-54109-and_instead_of_ampersands.rs:40:13
49+
error: `and` is not a logical operator
50+
--> $DIR/issue-54109-and_instead_of_ampersands.rs:46:13
4151
|
4252
LL | while a and b {
43-
| ^^^
44-
| |
45-
| expected one of `!`, `.`, `::`, `?`, `{`, or an operator
46-
| help: use `&&` instead of `and` for the boolean operator
53+
| ^^^ help: instead of `and`, use `&&` to perform logical conjunction: `&&`
54+
|
55+
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
4756

48-
error: expected one of `!`, `.`, `::`, `?`, `{`, or an operator, found `or`
49-
--> $DIR/issue-54109-and_instead_of_ampersands.rs:49:13
57+
error: `or` is not a logical operator
58+
--> $DIR/issue-54109-and_instead_of_ampersands.rs:54:13
5059
|
5160
LL | while a or b {
52-
| ^^
53-
| |
54-
| expected one of `!`, `.`, `::`, `?`, `{`, or an operator
55-
| help: use `||` instead of `or` for the boolean operator
61+
| ^^ help: instead of `or`, use `||` to perform logical disjunction: `||`
62+
|
63+
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
64+
65+
error[E0308]: mismatched types
66+
--> $DIR/issue-54109-and_instead_of_ampersands.rs:13:33
67+
|
68+
LL | let _recovery_witness: () = 0;
69+
| -- ^ expected `()`, found integer
70+
| |
71+
| expected due to this
5672

57-
error: aborting due to 6 previous errors
73+
error: aborting due to 9 previous errors
5874

75+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)