Recover parser from foo(_, _)

This commit is contained in:
Esteban Küber 2019-08-08 12:31:24 -07:00
parent 195d837f18
commit b7f7756566
5 changed files with 116 additions and 22 deletions

View File

@ -2052,9 +2052,23 @@ impl<'a> Parser<'a> {
while self.token != token::CloseDelim(token::Paren) {
es.push(match self.parse_expr() {
Ok(es) => es,
Err(err) => {
Err(mut err) => {
// recover from parse error in tuple list
return Ok(self.recover_seq_parse_error(token::Paren, lo, Err(err)));
match self.token.kind {
token::Ident(name, false)
if name == kw::Underscore && self.look_ahead(1, |t| {
t == &token::Comma
}) => {
// Special-case handling of `Foo<(_, _, _)>`
err.emit();
let sp = self.token.span;
self.bump();
self.mk_expr(sp, ExprKind::Err, ThinVec::new())
}
_ => return Ok(
self.recover_seq_parse_error(token::Paren, lo, Err(err)),
),
}
}
});
recovered = self.expect_one_of(
@ -2456,9 +2470,10 @@ impl<'a> Parser<'a> {
}
/// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
fn parse_dot_or_call_expr(&mut self,
already_parsed_attrs: Option<ThinVec<Attribute>>)
-> PResult<'a, P<Expr>> {
fn parse_dot_or_call_expr(
&mut self,
already_parsed_attrs: Option<ThinVec<Attribute>>,
) -> PResult<'a, P<Expr>> {
let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
let b = self.parse_bottom_expr();
@ -2466,16 +2481,16 @@ impl<'a> Parser<'a> {
self.parse_dot_or_call_expr_with(b, span, attrs)
}
fn parse_dot_or_call_expr_with(&mut self,
e0: P<Expr>,
lo: Span,
mut attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>> {
fn parse_dot_or_call_expr_with(
&mut self,
e0: P<Expr>,
lo: Span,
mut attrs: ThinVec<Attribute>,
) -> PResult<'a, P<Expr>> {
// Stitch the list of outer attributes onto the return value.
// A little bit ugly, but the best way given the current code
// structure
self.parse_dot_or_call_expr_with_(e0, lo)
.map(|expr|
self.parse_dot_or_call_expr_with_(e0, lo).map(|expr|
expr.map(|mut expr| {
attrs.extend::<Vec<_>>(expr.attrs.into());
expr.attrs = attrs;
@ -2483,10 +2498,7 @@ impl<'a> Parser<'a> {
ExprKind::If(..) if !expr.attrs.is_empty() => {
// Just point to the first attribute in there...
let span = expr.attrs[0].span;
self.span_err(span,
"attributes are not yet allowed on `if` \
expressions");
self.span_err(span, "attributes are not yet allowed on `if` expressions");
}
_ => {}
}
@ -2624,7 +2636,24 @@ impl<'a> Parser<'a> {
}
fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec<P<Expr>>> {
self.parse_paren_comma_seq(|p| p.parse_expr()).map(|(r, _)| r)
self.parse_paren_comma_seq(|p| {
match p.parse_expr() {
Ok(expr) => Ok(expr),
Err(mut err) => match p.token.kind {
token::Ident(name, false)
if name == kw::Underscore && p.look_ahead(1, |t| {
t == &token::Comma
}) => {
// Special-case handling of `foo(_, _, _)`
err.emit();
let sp = p.token.span;
p.bump();
Ok(p.mk_expr(sp, ExprKind::Err, ThinVec::new()))
}
_ => Err(err),
},
}
}).map(|(r, _)| r)
}
crate fn process_potential_macro_variable(&mut self) {
@ -2806,9 +2835,10 @@ impl<'a> Parser<'a> {
/// This parses an expression accounting for associativity and precedence of the operators in
/// the expression.
#[inline]
fn parse_assoc_expr(&mut self,
already_parsed_attrs: Option<ThinVec<Attribute>>)
-> PResult<'a, P<Expr>> {
fn parse_assoc_expr(
&mut self,
already_parsed_attrs: Option<ThinVec<Attribute>>,
) -> PResult<'a, P<Expr>> {
self.parse_assoc_expr_with(0, already_parsed_attrs.into())
}

View File

@ -5,6 +5,7 @@ fn main () {
//~| ERROR mismatched types
//~| ERROR invalid left-hand side expression
//~| ERROR expected expression, found reserved identifier `_`
//~| ERROR expected expression, found reserved identifier `_`
let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
//~^ ERROR no method named `iter` found for type `()` in the current scope
}

View File

@ -4,6 +4,12 @@ error: expected expression, found reserved identifier `_`
LL | let sr: Vec<(u32, _, _) = vec![];
| ^ expected expression
error: expected expression, found reserved identifier `_`
--> $DIR/issue-34334.rs:2:26
|
LL | let sr: Vec<(u32, _, _) = vec![];
| ^ expected expression
error: expected one of `,` or `>`, found `=`
--> $DIR/issue-34334.rs:2:29
|
@ -36,12 +42,12 @@ LL | let sr: Vec<(u32, _, _) = vec![];
| ^^^^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid
error[E0599]: no method named `iter` found for type `()` in the current scope
--> $DIR/issue-34334.rs:8:36
--> $DIR/issue-34334.rs:9:36
|
LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
| ^^^^
error: aborting due to 6 previous errors
error: aborting due to 7 previous errors
Some errors have detailed explanations: E0070, E0308, E0423, E0599.
For more information about an error, try `rustc --explain E0070`.

View File

@ -0,0 +1,19 @@
fn foo(a: usize, b: usize) -> usize { a }
struct S(usize, usize);
trait T {
fn baz(x: usize, y: usize) -> usize { x }
}
fn main() {
let _: usize = foo(_, _);
//~^ ERROR expected expression
//~| ERROR expected expression
let _: S = S(_, _);
//~^ ERROR expected expression
//~| ERROR expected expression
let _: usize = T::baz(_, _);
//~^ ERROR expected expression
//~| ERROR expected expression
}

View File

@ -0,0 +1,38 @@
error: expected expression, found reserved identifier `_`
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:24
|
LL | let _: usize = foo(_, _);
| ^ expected expression
error: expected expression, found reserved identifier `_`
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:27
|
LL | let _: usize = foo(_, _);
| ^ expected expression
error: expected expression, found reserved identifier `_`
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:18
|
LL | let _: S = S(_, _);
| ^ expected expression
error: expected expression, found reserved identifier `_`
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:21
|
LL | let _: S = S(_, _);
| ^ expected expression
error: expected expression, found reserved identifier `_`
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:27
|
LL | let _: usize = T::baz(_, _);
| ^ expected expression
error: expected expression, found reserved identifier `_`
--> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:30
|
LL | let _: usize = T::baz(_, _);
| ^ expected expression
error: aborting due to 6 previous errors