Skip to content

Commit c9e1f13

Browse files
committed
recover on 'mut', 'var', 'auto'
1 parent a0d2093 commit c9e1f13

File tree

4 files changed

+120
-3
lines changed

4 files changed

+120
-3
lines changed

src/librustc_parse/parser/stmt.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use syntax::ast::{AttrVec, Attribute, AttrStyle, VisibilityKind, MacStmtStyle, M
1414
use syntax::util::classify;
1515
use syntax::token;
1616
use syntax_pos::source_map::{respan, Span};
17-
use syntax_pos::symbol::kw;
17+
use syntax_pos::symbol::{kw, sym, Symbol};
1818

1919
use std::mem;
2020

@@ -39,8 +39,20 @@ impl<'a> Parser<'a> {
3939
let lo = self.token.span;
4040

4141
if self.eat_keyword(kw::Let) {
42-
let local = self.parse_local(attrs.into())?;
43-
return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Local(local))));
42+
return self.parse_local_mk(lo, attrs.into()).map(Some)
43+
}
44+
if self.is_kw_followed_by_ident(kw::Mut) {
45+
return self.recover_stmt_local(lo, attrs.into(), "missing `let`", "let mut");
46+
}
47+
if self.is_kw_followed_by_ident(kw::Auto) {
48+
self.bump(); // `auto`
49+
let msg = "to introduce a variable, write `let` instead of `auto`";
50+
return self.recover_stmt_local(lo, attrs.into(), msg, "let");
51+
}
52+
if self.is_kw_followed_by_ident(sym::var) {
53+
self.bump(); // `var`
54+
let msg = "to introduce a variable, write `let` instead of `var`";
55+
return self.recover_stmt_local(lo, attrs.into(), msg, "let");
4456
}
4557

4658
let mac_vis = respan(lo, VisibilityKind::Inherited);
@@ -189,6 +201,30 @@ impl<'a> Parser<'a> {
189201
}
190202
}
191203

204+
fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool {
205+
self.token.is_keyword(kw)
206+
&& self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
207+
}
208+
209+
fn recover_stmt_local(
210+
&mut self,
211+
span: Span,
212+
attrs: AttrVec,
213+
msg: &str,
214+
sugg: &str,
215+
) -> PResult<'a, Option<Stmt>> {
216+
let stmt = self.parse_local_mk(span, attrs)?;
217+
self.struct_span_err(stmt.span, "invalid variable declaration")
218+
.span_suggestion_short(span, msg, sugg.to_string(), Applicability::MachineApplicable)
219+
.emit();
220+
Ok(Some(stmt))
221+
}
222+
223+
fn parse_local_mk(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> {
224+
let local = self.parse_local(attrs.into())?;
225+
Ok(self.mk_stmt(lo.to(self.prev_span), StmtKind::Local(local)))
226+
}
227+
192228
/// Parses a local variable declaration.
193229
fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
194230
let lo = self.prev_span;

src/libsyntax_pos/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,7 @@ symbols! {
773773
usize,
774774
v1,
775775
val,
776+
var,
776777
vec,
777778
Vec,
778779
vis,
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
fn main() {
2+
auto n = 0;//~ ERROR invalid variable declaration
3+
//~^ HELP to introduce a variable, write `let` instead of `auto`
4+
auto m;//~ ERROR invalid variable declaration
5+
//~^ HELP to introduce a variable, write `let` instead of `auto`
6+
m = 0;
7+
8+
var n = 0;//~ ERROR invalid variable declaration
9+
//~^ HELP to introduce a variable, write `let` instead of `var`
10+
var m;//~ ERROR invalid variable declaration
11+
//~^ HELP to introduce a variable, write `let` instead of `var`
12+
m = 0;
13+
14+
mut n = 0;//~ ERROR invalid variable declaration
15+
//~^ HELP missing `let`
16+
mut var;//~ ERROR invalid variable declaration
17+
//~^ HELP missing `let`
18+
var = 0;
19+
20+
let _recovery_witness: () = 0; //~ ERROR mismatched types
21+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
error: invalid variable declaration
2+
--> $DIR/issue-65257-invalid-var-decl-recovery.rs:2:5
3+
|
4+
LL | auto n = 0;
5+
| ----^^^^^^
6+
| |
7+
| help: to introduce a variable, write `let` instead of `auto`
8+
9+
error: invalid variable declaration
10+
--> $DIR/issue-65257-invalid-var-decl-recovery.rs:4:5
11+
|
12+
LL | auto m;
13+
| ----^^
14+
| |
15+
| help: to introduce a variable, write `let` instead of `auto`
16+
17+
error: invalid variable declaration
18+
--> $DIR/issue-65257-invalid-var-decl-recovery.rs:8:5
19+
|
20+
LL | var n = 0;
21+
| ---^^^^^^
22+
| |
23+
| help: to introduce a variable, write `let` instead of `var`
24+
25+
error: invalid variable declaration
26+
--> $DIR/issue-65257-invalid-var-decl-recovery.rs:10:5
27+
|
28+
LL | var m;
29+
| ---^^
30+
| |
31+
| help: to introduce a variable, write `let` instead of `var`
32+
33+
error: invalid variable declaration
34+
--> $DIR/issue-65257-invalid-var-decl-recovery.rs:14:5
35+
|
36+
LL | mut n = 0;
37+
| ---^^^^^^
38+
| |
39+
| help: missing `let`
40+
41+
error: invalid variable declaration
42+
--> $DIR/issue-65257-invalid-var-decl-recovery.rs:16:5
43+
|
44+
LL | mut var;
45+
| ---^^^^
46+
| |
47+
| help: missing `let`
48+
49+
error[E0308]: mismatched types
50+
--> $DIR/issue-65257-invalid-var-decl-recovery.rs:20:33
51+
|
52+
LL | let _recovery_witness: () = 0;
53+
| -- ^ expected `()`, found integer
54+
| |
55+
| expected due to this
56+
57+
error: aborting due to 7 previous errors
58+
59+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)