Skip to content

Commit 8605d87

Browse files
committed
Continue parsing after recovering from missing close delim
1 parent 3942ad4 commit 8605d87

11 files changed

+163
-107
lines changed

src/libsyntax/parse/parser.rs

+86-56
Original file line numberDiff line numberDiff line change
@@ -649,10 +649,11 @@ impl<'a> Parser<'a> {
649649
TokenType::Token(t) => Some((*t).clone()),
650650
_ => None,
651651
}));
652-
for (i, (delim, span)) in self.open_braces.iter().enumerate() {
652+
// we want to use the last closing delim that would apply
653+
for (i, (delim, span)) in self.open_braces.iter().enumerate().rev() {
653654
if tokens.contains(&token::CloseDelim(*delim)) && self.span > *span {
654655
pos = Some(i);
655-
// do not break, we want to use the last one that would apply
656+
break;
656657
}
657658
}
658659
match pos {
@@ -681,6 +682,7 @@ impl<'a> Parser<'a> {
681682
Applicability::MaybeIncorrect,
682683
);
683684
err.emit();
685+
self.expected_tokens.clear(); // reduce errors
684686
Ok(())
685687
}
686688
_ => Err(err),
@@ -689,11 +691,11 @@ impl<'a> Parser<'a> {
689691

690692
/// Expect and consume the token t. Signal an error if
691693
/// the next token is not t.
692-
pub fn expect(&mut self, t: &token::Token) -> PResult<'a, ()> {
694+
pub fn expect(&mut self, t: &token::Token) -> PResult<'a, bool /* recovered */> {
693695
if self.expected_tokens.is_empty() {
694696
if self.token == *t {
695697
self.bump();
696-
Ok(())
698+
Ok(false)
697699
} else {
698700
let token_str = pprust::token_to_string(t);
699701
let this_token_str = self.this_token_to_string();
@@ -720,7 +722,7 @@ impl<'a> Parser<'a> {
720722
err.span_label(self.span, "unexpected token");
721723
}
722724
}
723-
self.recover_closing_delimiter(&[t.clone()], err)
725+
self.recover_closing_delimiter(&[t.clone()], err).map(|_| true)
724726
}
725727
} else {
726728
self.expect_one_of(slice::from_ref(t), &[])
@@ -730,9 +732,11 @@ impl<'a> Parser<'a> {
730732
/// Expect next token to be edible or inedible token. If edible,
731733
/// then consume it; if inedible, then return without consuming
732734
/// anything. Signal a fatal error if next token is unexpected.
733-
fn expect_one_of(&mut self,
735+
fn expect_one_of(
736+
&mut self,
734737
edible: &[token::Token],
735-
inedible: &[token::Token]) -> PResult<'a, ()>{
738+
inedible: &[token::Token],
739+
) -> PResult<'a, bool /* recovered */>{
736740
fn tokens_to_string(tokens: &[TokenType]) -> String {
737741
let mut i = tokens.iter();
738742
// This might be a sign we need a connect method on Iterator.
@@ -752,10 +756,10 @@ impl<'a> Parser<'a> {
752756
}
753757
if edible.contains(&self.token) {
754758
self.bump();
755-
Ok(())
759+
Ok(false)
756760
} else if inedible.contains(&self.token) {
757761
// leave it in the input
758-
Ok(())
762+
Ok(false)
759763
} else {
760764
let mut expected = edible.iter()
761765
.map(|x| TokenType::Token(x.clone()))
@@ -813,7 +817,7 @@ impl<'a> Parser<'a> {
813817
err.span_label(self.span, "unexpected token");
814818
}
815819
}
816-
self.recover_closing_delimiter(edible, err)
820+
self.recover_closing_delimiter(edible, err).map(|_| true)
817821
}
818822
}
819823

@@ -1112,15 +1116,18 @@ impl<'a> Parser<'a> {
11121116
/// Parse a sequence, including the closing delimiter. The function
11131117
/// f must consume tokens until reaching the next separator or
11141118
/// closing bracket.
1115-
pub fn parse_seq_to_end<T, F>(&mut self,
1119+
pub fn parse_seq_to_end<T, F>(
1120+
&mut self,
11161121
ket: &token::Token,
11171122
sep: SeqSep,
1118-
f: F)
1119-
-> PResult<'a, Vec<T>> where
1120-
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
1123+
f: F,
1124+
) -> PResult<'a, Vec<T>>
1125+
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
11211126
{
1122-
let val = self.parse_seq_to_before_end(ket, sep, f)?;
1123-
self.bump();
1127+
let (val, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
1128+
if !recovered {
1129+
self.bump();
1130+
}
11241131
Ok(val)
11251132
}
11261133

@@ -1132,7 +1139,7 @@ impl<'a> Parser<'a> {
11321139
ket: &token::Token,
11331140
sep: SeqSep,
11341141
f: F,
1135-
) -> PResult<'a, Vec<T>>
1142+
) -> PResult<'a, (Vec<T>, bool /* recovered */)>
11361143
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
11371144
{
11381145
self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
@@ -1144,10 +1151,11 @@ impl<'a> Parser<'a> {
11441151
sep: SeqSep,
11451152
expect: TokenExpectType,
11461153
mut f: F,
1147-
) -> PResult<'a, Vec<T>>
1154+
) -> PResult<'a, (Vec<T>, bool /* recovered */)>
11481155
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
11491156
{
11501157
let mut first: bool = true;
1158+
let mut recovered = false;
11511159
let mut v = vec![];
11521160
while !kets.iter().any(|k| {
11531161
match expect {
@@ -1163,29 +1171,38 @@ impl<'a> Parser<'a> {
11631171
if first {
11641172
first = false;
11651173
} else {
1166-
if let Err(mut e) = self.expect(t) {
1167-
// Attempt to keep parsing if it was a similar separator
1168-
if let Some(ref tokens) = t.similar_tokens() {
1169-
if tokens.contains(&self.token) {
1170-
self.bump();
1171-
}
1174+
match self.expect(t) {
1175+
Ok(true) => {
1176+
recovered = true;
1177+
break;
11721178
}
1173-
e.emit();
1174-
// Attempt to keep parsing if it was an omitted separator
1175-
match f(self) {
1176-
Ok(t) => {
1177-
v.push(t);
1178-
continue;
1179-
},
1180-
Err(mut err) => {
1181-
err.cancel();
1182-
let kets: Vec<token::Token> = kets.iter()
1183-
.map(|t| (*t).clone())
1184-
.collect();
1185-
let _ = self.recover_closing_delimiter(&kets[..], e);
1186-
break;
1179+
Err(mut e) => {
1180+
// Attempt to keep parsing if it was a similar separator
1181+
if let Some(ref tokens) = t.similar_tokens() {
1182+
if tokens.contains(&self.token) {
1183+
self.bump();
1184+
}
1185+
}
1186+
e.emit();
1187+
// Attempt to keep parsing if it was an omitted separator
1188+
match f(self) {
1189+
Ok(t) => {
1190+
v.push(t);
1191+
continue;
1192+
},
1193+
Err(mut err) => {
1194+
err.cancel();
1195+
let kets: Vec<token::Token> = kets.iter()
1196+
.map(|t| (*t).clone())
1197+
.collect();
1198+
if let Ok(()) = self.recover_closing_delimiter(&kets[..], e) {
1199+
recovered = true;
1200+
}
1201+
break;
1202+
}
11871203
}
11881204
}
1205+
_ => {}
11891206
}
11901207
}
11911208
}
@@ -1202,13 +1219,13 @@ impl<'a> Parser<'a> {
12021219
Ok(t) => t,
12031220
Err(e) => {
12041221
let kets: Vec<token::Token> = kets.iter().map(|t| (*t).clone()).collect();
1205-
return self.recover_closing_delimiter(&kets[..], e).map(|_| v);
1222+
return self.recover_closing_delimiter(&kets[..], e).map(|_| (v, true));
12061223
}
12071224
};
12081225
v.push(t);
12091226
}
12101227

1211-
Ok(v)
1228+
Ok((v, recovered))
12121229
}
12131230

12141231
/// Parse a sequence, including the closing delimiter. The function
@@ -1224,8 +1241,10 @@ impl<'a> Parser<'a> {
12241241
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
12251242
{
12261243
self.expect(bra)?;
1227-
let result = self.parse_seq_to_before_end(ket, sep, f)?;
1228-
self.eat(ket);
1244+
let (result, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
1245+
if !recovered {
1246+
self.eat(ket);
1247+
}
12291248
Ok(result)
12301249
}
12311250

@@ -1253,6 +1272,7 @@ impl<'a> Parser<'a> {
12531272
self.span = next.sp;
12541273
self.token = next.tok;
12551274
self.expected_tokens.clear();
1275+
self.expected_tokens.clear();
12561276
// check after each token
12571277
self.process_potential_macro_variable();
12581278
}
@@ -2135,12 +2155,14 @@ impl<'a> Parser<'a> {
21352155
} else {
21362156
// `(T, U) -> R`
21372157
self.bump(); // `(`
2138-
let inputs = self.parse_seq_to_before_tokens(
2158+
let (inputs, recovered) = self.parse_seq_to_before_tokens(
21392159
&[&token::CloseDelim(token::Paren)],
21402160
SeqSep::trailing_allowed(token::Comma),
21412161
TokenExpectType::Expect,
21422162
|p| p.parse_ty())?;
2143-
self.bump(); // `)`
2163+
if !recovered {
2164+
self.bump(); // `)`
2165+
}
21442166
let span = lo.to(self.prev_span);
21452167
let output = if self.eat(&token::RArrow) {
21462168
Some(self.parse_ty_common(false, false)?)
@@ -2564,6 +2586,7 @@ impl<'a> Parser<'a> {
25642586
self.bump();
25652587
let mut fields = Vec::new();
25662588
let mut base = None;
2589+
let mut recovered = false;
25672590

25682591
attrs.extend(self.parse_inner_attributes()?);
25692592

@@ -2615,7 +2638,7 @@ impl<'a> Parser<'a> {
26152638

26162639
match self.expect_one_of(&[token::Comma],
26172640
&[token::CloseDelim(token::Brace)]) {
2618-
Ok(()) => {}
2641+
Ok(r) => recovered = r,
26192642
Err(mut e) => {
26202643
e.emit();
26212644
self.recover_stmt();
@@ -2625,7 +2648,9 @@ impl<'a> Parser<'a> {
26252648
}
26262649

26272650
let span = lo.to(self.span);
2628-
self.expect(&token::CloseDelim(token::Brace))?;
2651+
if !recovered {
2652+
self.expect(&token::CloseDelim(token::Brace))?;
2653+
}
26292654
return Ok(self.mk_expr(span, ExprKind::Struct(pth, fields, base), attrs));
26302655
}
26312656

@@ -5502,24 +5527,29 @@ impl<'a> Parser<'a> {
55025527

55035528
// Parse the rest of the function parameter list.
55045529
let sep = SeqSep::trailing_allowed(token::Comma);
5505-
let fn_inputs = if let Some(self_arg) = self_arg {
5530+
let (fn_inputs, recovered) = if let Some(self_arg) = self_arg {
55065531
if self.check(&token::CloseDelim(token::Paren)) {
5507-
vec![self_arg]
5532+
(vec![self_arg], false)
55085533
} else if self.eat(&token::Comma) {
55095534
let mut fn_inputs = vec![self_arg];
5510-
fn_inputs.append(&mut self.parse_seq_to_before_end(
5511-
&token::CloseDelim(token::Paren), sep, parse_arg_fn)?
5512-
);
5513-
fn_inputs
5535+
let (mut inputs, recovered) = self.parse_seq_to_before_end(
5536+
&token::CloseDelim(token::Paren),
5537+
sep,
5538+
parse_arg_fn,
5539+
)?;
5540+
fn_inputs.append(&mut inputs);
5541+
(fn_inputs, recovered)
55145542
} else {
55155543
return self.unexpected();
55165544
}
55175545
} else {
55185546
self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?
55195547
};
55205548

5521-
// Parse closing paren and return type.
5522-
self.expect(&token::CloseDelim(token::Paren))?;
5549+
if !recovered {
5550+
// Parse closing paren and return type.
5551+
self.expect(&token::CloseDelim(token::Paren))?;
5552+
}
55235553
Ok(P(FnDecl {
55245554
inputs: fn_inputs,
55255555
output: self.parse_ret_ty(true)?,
@@ -5534,7 +5564,7 @@ impl<'a> Parser<'a> {
55345564
Vec::new()
55355565
} else {
55365566
self.expect(&token::BinOp(token::Or))?;
5537-
let args = self.parse_seq_to_before_tokens(
5567+
let (args, _) = self.parse_seq_to_before_tokens(
55385568
&[&token::BinOp(token::Or), &token::OrOr],
55395569
SeqSep::trailing_allowed(token::Comma),
55405570
TokenExpectType::NoExpect,
@@ -7458,7 +7488,7 @@ impl<'a> Parser<'a> {
74587488
// eat a matched-delimiter token tree:
74597489
let (delim, tts) = self.expect_delimited_token_tree()?;
74607490
if delim != MacDelimiter::Brace {
7461-
self.expect(&token::Semi)?
7491+
self.expect(&token::Semi)?;
74627492
}
74637493

74647494
Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts, delim })))

src/test/ui/parser-recovery-3.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ impl A {
1414
fn banana(&mut self) {
1515
fn peach(this: &Self, foo: usize {
1616
//~^ ERROR expected one of
17-
//~| ERROR expected pattern
17+
//~| ERROR can't use type parameters from outer function
1818
}
1919
}
20-
//~^ ERROR expected one of
21-
//~| ERROR incorrect close delimiter
20+
//~^ ERROR incorrect close delimiter
21+
//~| ERROR expected expression
2222
}
2323

2424
fn main() {}

src/test/ui/parser-recovery-3.stderr

+15-8
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,24 @@ LL | fn peach(this: &Self, foo: usize {
1818
| | help: ...the missing `)` may belong here
1919
| if you meant to close this...
2020

21-
error: expected pattern, found `{`
22-
--> $DIR/parser-recovery-3.rs:15:42
23-
|
24-
LL | fn peach(this: &Self, foo: usize {
25-
| ^ expected pattern
26-
27-
error: expected one of `->`, `where`, or `{`, found `}`
21+
error: expected expression, found `)`
2822
--> $DIR/parser-recovery-3.rs:19:5
2923
|
3024
LL | }
31-
| ^ expected one of `->`, `where`, or `{` here
25+
| ^ expected expression
26+
27+
error[E0401]: can't use type parameters from outer function
28+
--> $DIR/parser-recovery-3.rs:15:25
29+
|
30+
LL | impl A {
31+
| ---- `Self` type implicitly declared here, by this `impl`
32+
LL | fn banana(&mut self) {
33+
LL | fn peach(this: &Self, foo: usize {
34+
| ^^^^
35+
| |
36+
| use of type variable from outer function
37+
| use a type here instead
3238

3339
error: aborting due to 4 previous errors
3440

41+
For more information about this error, try `rustc --explain E0401`.

src/test/ui/parser-recovery-4.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ fn main() {
1616
foo(x
1717
bar()
1818
//~^ ERROR expected one of
19-
//~^^^ ERROR this function takes 1 parameter but 2 parameters were supplied
19+
//~| ERROR expected one of
2020
}
2121
//~^ ERROR incorrect close delimiter

0 commit comments

Comments
 (0)