From c9e1f13f6eb9d21224c083eb07d894adffc7ec96 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 3 Dec 2019 18:08:19 +0100 Subject: [PATCH] recover on 'mut', 'var', 'auto' --- src/librustc_parse/parser/stmt.rs | 42 ++++++++++++- src/libsyntax_pos/symbol.rs | 1 + .../issue-65257-invalid-var-decl-recovery.rs | 21 +++++++ ...sue-65257-invalid-var-decl-recovery.stderr | 59 +++++++++++++++++++ 4 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs create mode 100644 src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index a0808063116..abee24e2b09 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -14,7 +14,7 @@ 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; @@ -39,8 +39,20 @@ fn parse_stmt_without_recovery( 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); @@ -189,6 +201,30 @@ fn error_outer_attrs(&self, attrs: &[Attribute]) { } } + 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> { + 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> { let lo = self.prev_span; diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index ae34064c926..d3e80fc4fdd 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -773,6 +773,7 @@ usize, v1, val, + var, vec, Vec, vis, diff --git a/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs new file mode 100644 index 00000000000..7efc4174874 --- /dev/null +++ b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs @@ -0,0 +1,21 @@ +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 +} diff --git a/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr new file mode 100644 index 00000000000..429c12265bd --- /dev/null +++ b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr @@ -0,0 +1,59 @@ +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`. -- 2.44.0