Skip to content

Commit b7f7756

Browse files
committed
Recover parser from foo(_, _)
1 parent 195d837 commit b7f7756

File tree

5 files changed

+116
-22
lines changed

5 files changed

+116
-22
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,9 +2052,23 @@ impl<'a> Parser<'a> {
20522052
while self.token != token::CloseDelim(token::Paren) {
20532053
es.push(match self.parse_expr() {
20542054
Ok(es) => es,
2055-
Err(err) => {
2055+
Err(mut err) => {
20562056
// recover from parse error in tuple list
2057-
return Ok(self.recover_seq_parse_error(token::Paren, lo, Err(err)));
2057+
match self.token.kind {
2058+
token::Ident(name, false)
2059+
if name == kw::Underscore && self.look_ahead(1, |t| {
2060+
t == &token::Comma
2061+
}) => {
2062+
// Special-case handling of `Foo<(_, _, _)>`
2063+
err.emit();
2064+
let sp = self.token.span;
2065+
self.bump();
2066+
self.mk_expr(sp, ExprKind::Err, ThinVec::new())
2067+
}
2068+
_ => return Ok(
2069+
self.recover_seq_parse_error(token::Paren, lo, Err(err)),
2070+
),
2071+
}
20582072
}
20592073
});
20602074
recovered = self.expect_one_of(
@@ -2456,37 +2470,35 @@ impl<'a> Parser<'a> {
24562470
}
24572471

24582472
/// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
2459-
fn parse_dot_or_call_expr(&mut self,
2460-
already_parsed_attrs: Option<ThinVec<Attribute>>)
2461-
-> PResult<'a, P<Expr>> {
2473+
fn parse_dot_or_call_expr(
2474+
&mut self,
2475+
already_parsed_attrs: Option<ThinVec<Attribute>>,
2476+
) -> PResult<'a, P<Expr>> {
24622477
let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
24632478

24642479
let b = self.parse_bottom_expr();
24652480
let (span, b) = self.interpolated_or_expr_span(b)?;
24662481
self.parse_dot_or_call_expr_with(b, span, attrs)
24672482
}
24682483

2469-
fn parse_dot_or_call_expr_with(&mut self,
2470-
e0: P<Expr>,
2471-
lo: Span,
2472-
mut attrs: ThinVec<Attribute>)
2473-
-> PResult<'a, P<Expr>> {
2484+
fn parse_dot_or_call_expr_with(
2485+
&mut self,
2486+
e0: P<Expr>,
2487+
lo: Span,
2488+
mut attrs: ThinVec<Attribute>,
2489+
) -> PResult<'a, P<Expr>> {
24742490
// Stitch the list of outer attributes onto the return value.
24752491
// A little bit ugly, but the best way given the current code
24762492
// structure
2477-
self.parse_dot_or_call_expr_with_(e0, lo)
2478-
.map(|expr|
2493+
self.parse_dot_or_call_expr_with_(e0, lo).map(|expr|
24792494
expr.map(|mut expr| {
24802495
attrs.extend::<Vec<_>>(expr.attrs.into());
24812496
expr.attrs = attrs;
24822497
match expr.node {
24832498
ExprKind::If(..) if !expr.attrs.is_empty() => {
24842499
// Just point to the first attribute in there...
24852500
let span = expr.attrs[0].span;
2486-
2487-
self.span_err(span,
2488-
"attributes are not yet allowed on `if` \
2489-
expressions");
2501+
self.span_err(span, "attributes are not yet allowed on `if` expressions");
24902502
}
24912503
_ => {}
24922504
}
@@ -2624,7 +2636,24 @@ impl<'a> Parser<'a> {
26242636
}
26252637

26262638
fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec<P<Expr>>> {
2627-
self.parse_paren_comma_seq(|p| p.parse_expr()).map(|(r, _)| r)
2639+
self.parse_paren_comma_seq(|p| {
2640+
match p.parse_expr() {
2641+
Ok(expr) => Ok(expr),
2642+
Err(mut err) => match p.token.kind {
2643+
token::Ident(name, false)
2644+
if name == kw::Underscore && p.look_ahead(1, |t| {
2645+
t == &token::Comma
2646+
}) => {
2647+
// Special-case handling of `foo(_, _, _)`
2648+
err.emit();
2649+
let sp = p.token.span;
2650+
p.bump();
2651+
Ok(p.mk_expr(sp, ExprKind::Err, ThinVec::new()))
2652+
}
2653+
_ => Err(err),
2654+
},
2655+
}
2656+
}).map(|(r, _)| r)
26282657
}
26292658

26302659
crate fn process_potential_macro_variable(&mut self) {
@@ -2806,9 +2835,10 @@ impl<'a> Parser<'a> {
28062835
/// This parses an expression accounting for associativity and precedence of the operators in
28072836
/// the expression.
28082837
#[inline]
2809-
fn parse_assoc_expr(&mut self,
2810-
already_parsed_attrs: Option<ThinVec<Attribute>>)
2811-
-> PResult<'a, P<Expr>> {
2838+
fn parse_assoc_expr(
2839+
&mut self,
2840+
already_parsed_attrs: Option<ThinVec<Attribute>>,
2841+
) -> PResult<'a, P<Expr>> {
28122842
self.parse_assoc_expr_with(0, already_parsed_attrs.into())
28132843
}
28142844

src/test/ui/issues/issue-34334.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ fn main () {
55
//~| ERROR mismatched types
66
//~| ERROR invalid left-hand side expression
77
//~| ERROR expected expression, found reserved identifier `_`
8+
//~| ERROR expected expression, found reserved identifier `_`
89
let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
910
//~^ ERROR no method named `iter` found for type `()` in the current scope
1011
}

src/test/ui/issues/issue-34334.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ error: expected expression, found reserved identifier `_`
44
LL | let sr: Vec<(u32, _, _) = vec![];
55
| ^ expected expression
66

7+
error: expected expression, found reserved identifier `_`
8+
--> $DIR/issue-34334.rs:2:26
9+
|
10+
LL | let sr: Vec<(u32, _, _) = vec![];
11+
| ^ expected expression
12+
713
error: expected one of `,` or `>`, found `=`
814
--> $DIR/issue-34334.rs:2:29
915
|
@@ -36,12 +42,12 @@ LL | let sr: Vec<(u32, _, _) = vec![];
3642
| ^^^^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid
3743

3844
error[E0599]: no method named `iter` found for type `()` in the current scope
39-
--> $DIR/issue-34334.rs:8:36
45+
--> $DIR/issue-34334.rs:9:36
4046
|
4147
LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
4248
| ^^^^
4349

44-
error: aborting due to 6 previous errors
50+
error: aborting due to 7 previous errors
4551

4652
Some errors have detailed explanations: E0070, E0308, E0423, E0599.
4753
For more information about an error, try `rustc --explain E0070`.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
fn foo(a: usize, b: usize) -> usize { a }
2+
3+
struct S(usize, usize);
4+
5+
trait T {
6+
fn baz(x: usize, y: usize) -> usize { x }
7+
}
8+
9+
fn main() {
10+
let _: usize = foo(_, _);
11+
//~^ ERROR expected expression
12+
//~| ERROR expected expression
13+
let _: S = S(_, _);
14+
//~^ ERROR expected expression
15+
//~| ERROR expected expression
16+
let _: usize = T::baz(_, _);
17+
//~^ ERROR expected expression
18+
//~| ERROR expected expression
19+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error: expected expression, found reserved identifier `_`
2+
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:24
3+
|
4+
LL | let _: usize = foo(_, _);
5+
| ^ expected expression
6+
7+
error: expected expression, found reserved identifier `_`
8+
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:27
9+
|
10+
LL | let _: usize = foo(_, _);
11+
| ^ expected expression
12+
13+
error: expected expression, found reserved identifier `_`
14+
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:18
15+
|
16+
LL | let _: S = S(_, _);
17+
| ^ expected expression
18+
19+
error: expected expression, found reserved identifier `_`
20+
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:21
21+
|
22+
LL | let _: S = S(_, _);
23+
| ^ expected expression
24+
25+
error: expected expression, found reserved identifier `_`
26+
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:27
27+
|
28+
LL | let _: usize = T::baz(_, _);
29+
| ^ expected expression
30+
31+
error: expected expression, found reserved identifier `_`
32+
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:30
33+
|
34+
LL | let _: usize = T::baz(_, _);
35+
| ^ expected expression
36+
37+
error: aborting due to 6 previous errors
38+

0 commit comments

Comments
 (0)