use syntax::util::classify;
use syntax::token;
use syntax_pos::source_map::{respan, Span};
-use syntax_pos::symbol::kw;
+use syntax_pos::symbol::{kw, sym, Symbol};
use std::mem;
let lo = self.token.span;
if self.eat_keyword(kw::Let) {
- let local = self.parse_local(attrs.into())?;
- return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Local(local))));
+ return self.parse_local_mk(lo, attrs.into()).map(Some)
+ }
+ if self.is_kw_followed_by_ident(kw::Mut) {
+ return self.recover_stmt_local(lo, attrs.into(), "missing `let`", "let mut");
+ }
+ if self.is_kw_followed_by_ident(kw::Auto) {
+ self.bump(); // `auto`
+ let msg = "to introduce a variable, write `let` instead of `auto`";
+ return self.recover_stmt_local(lo, attrs.into(), msg, "let");
+ }
+ if self.is_kw_followed_by_ident(sym::var) {
+ self.bump(); // `var`
+ let msg = "to introduce a variable, write `let` instead of `var`";
+ return self.recover_stmt_local(lo, attrs.into(), msg, "let");
}
let mac_vis = respan(lo, VisibilityKind::Inherited);
}
}
+ fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool {
+ self.token.is_keyword(kw)
+ && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
+ }
+
+ fn recover_stmt_local(
+ &mut self,
+ span: Span,
+ attrs: AttrVec,
+ msg: &str,
+ sugg: &str,
+ ) -> PResult<'a, Option<Stmt>> {
+ let stmt = self.parse_local_mk(span, attrs)?;
+ self.struct_span_err(stmt.span, "invalid variable declaration")
+ .span_suggestion_short(span, msg, sugg.to_string(), Applicability::MachineApplicable)
+ .emit();
+ Ok(Some(stmt))
+ }
+
+ fn parse_local_mk(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> {
+ let local = self.parse_local(attrs.into())?;
+ Ok(self.mk_stmt(lo.to(self.prev_span), StmtKind::Local(local)))
+ }
+
/// Parses a local variable declaration.
fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
let lo = self.prev_span;
--- /dev/null
+fn main() {
+ auto n = 0;//~ ERROR invalid variable declaration
+ //~^ HELP to introduce a variable, write `let` instead of `auto`
+ auto m;//~ ERROR invalid variable declaration
+ //~^ HELP to introduce a variable, write `let` instead of `auto`
+ m = 0;
+
+ var n = 0;//~ ERROR invalid variable declaration
+ //~^ HELP to introduce a variable, write `let` instead of `var`
+ var m;//~ ERROR invalid variable declaration
+ //~^ HELP to introduce a variable, write `let` instead of `var`
+ m = 0;
+
+ mut n = 0;//~ ERROR invalid variable declaration
+ //~^ HELP missing `let`
+ mut var;//~ ERROR invalid variable declaration
+ //~^ HELP missing `let`
+ var = 0;
+
+ let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
--- /dev/null
+error: invalid variable declaration
+ --> $DIR/issue-65257-invalid-var-decl-recovery.rs:2:5
+ |
+LL | auto n = 0;
+ | ----^^^^^^
+ | |
+ | help: to introduce a variable, write `let` instead of `auto`
+
+error: invalid variable declaration
+ --> $DIR/issue-65257-invalid-var-decl-recovery.rs:4:5
+ |
+LL | auto m;
+ | ----^^
+ | |
+ | help: to introduce a variable, write `let` instead of `auto`
+
+error: invalid variable declaration
+ --> $DIR/issue-65257-invalid-var-decl-recovery.rs:8:5
+ |
+LL | var n = 0;
+ | ---^^^^^^
+ | |
+ | help: to introduce a variable, write `let` instead of `var`
+
+error: invalid variable declaration
+ --> $DIR/issue-65257-invalid-var-decl-recovery.rs:10:5
+ |
+LL | var m;
+ | ---^^
+ | |
+ | help: to introduce a variable, write `let` instead of `var`
+
+error: invalid variable declaration
+ --> $DIR/issue-65257-invalid-var-decl-recovery.rs:14:5
+ |
+LL | mut n = 0;
+ | ---^^^^^^
+ | |
+ | help: missing `let`
+
+error: invalid variable declaration
+ --> $DIR/issue-65257-invalid-var-decl-recovery.rs:16:5
+ |
+LL | mut var;
+ | ---^^^^
+ | |
+ | help: missing `let`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-65257-invalid-var-decl-recovery.rs:20:33
+ |
+LL | let _recovery_witness: () = 0;
+ | -- ^ expected `()`, found integer
+ | |
+ | expected due to this
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.