Ok(Some(if self.token.is_keyword(kw::Let) {
self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
- } else if self.is_kw_followed_by_ident(kw::Mut) {
- self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::MissingLet)?
- } else if self.is_kw_followed_by_ident(kw::Auto) {
+ } else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() {
+ self.recover_stmt_local_after_let(lo, attrs, InvalidVariableDeclarationSub::MissingLet)?
+ } else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() {
self.bump(); // `auto`
- self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotAuto)?
- } else if self.is_kw_followed_by_ident(sym::var) {
+ self.recover_stmt_local_after_let(
+ lo,
+ attrs,
+ InvalidVariableDeclarationSub::UseLetNotAuto,
+ )?
+ } else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() {
self.bump(); // `var`
- self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotVar)?
+ self.recover_stmt_local_after_let(
+ lo,
+ attrs,
+ InvalidVariableDeclarationSub::UseLetNotVar,
+ )?
} else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
// We have avoided contextual keywords like `union`, items with `crate` visibility,
// or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
// Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
- this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
+ this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true))
})?;
Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
} else {
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
- let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+ let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?;
StmtKind::Expr(e)
};
Ok(self.mk_stmt(lo.to(hi), kind))
}
}
- fn recover_stmt_local(
+ fn recover_stmt_local_after_let(
&mut self,
lo: Span,
attrs: AttrWrapper,
subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub,
) -> PResult<'a, Stmt> {
- let stmt = self.recover_local_after_let(lo, attrs)?;
+ let stmt =
+ self.collect_tokens_trailing_token(attrs, ForceCollect::Yes, |this, attrs| {
+ let local = this.parse_local(attrs)?;
+ // FIXME - maybe capture semicolon in recovery?
+ Ok((
+ this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)),
+ TrailingToken::None,
+ ))
+ })?;
self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
Ok(stmt)
}
})
}
- fn recover_local_after_let(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> {
- self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
- let local = this.parse_local(attrs)?;
- // FIXME - maybe capture semicolon in recovery?
- Ok((
- this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)),
- TrailingToken::None,
- ))
- })
- }
-
/// Parses a local variable declaration.
fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
let lo = self.prev_token.span;