@@ -171,6 +171,12 @@ impl RecoverQPath for Expr {
171171 }
172172}
173173
174+ /// Control whether the closing delimiter should be consumed when calling `Parser::consume_block`.
175+ crate enum ConsumeClosingDelim {
176+ Yes ,
177+ No ,
178+ }
179+
174180impl < ' a > Parser < ' a > {
175181 pub fn fatal ( & self , m : & str ) -> DiagnosticBuilder < ' a > {
176182 self . span_fatal ( self . token . span , m)
@@ -1105,8 +1111,8 @@ impl<'a> Parser<'a> {
11051111 Ok ( x) => x,
11061112 Err ( mut err) => {
11071113 err. emit ( ) ;
1108- // Recover from parse error.
1109- self . consume_block ( delim) ;
1114+ // Recover from parse error, callers expect the closing delim to be consumed .
1115+ self . consume_block ( delim, ConsumeClosingDelim :: Yes ) ;
11101116 self . mk_expr ( lo. to ( self . prev_span ) , ExprKind :: Err , ThinVec :: new ( ) )
11111117 }
11121118 }
@@ -1135,6 +1141,11 @@ impl<'a> Parser<'a> {
11351141 // Don't attempt to recover from this unclosed delimiter more than once.
11361142 let unmatched = self . unclosed_delims . remove ( pos) ;
11371143 let delim = TokenType :: Token ( token:: CloseDelim ( unmatched. expected_delim ) ) ;
1144+ if unmatched. found_delim . is_none ( ) {
1145+ // We encountered `Eof`, set this fact here to avoid complaining about missing
1146+ // `fn main()` when we found place to suggest the closing brace.
1147+ * self . sess . reached_eof . borrow_mut ( ) = true ;
1148+ }
11381149
11391150 // We want to suggest the inclusion of the closing delimiter where it makes
11401151 // the most sense, which is immediately after the last token:
@@ -1154,17 +1165,29 @@ impl<'a> Parser<'a> {
11541165 delim. to_string ( ) ,
11551166 Applicability :: MaybeIncorrect ,
11561167 ) ;
1157- err. emit ( ) ;
1158- self . expected_tokens . clear ( ) ; // reduce errors
1159- Ok ( true )
1168+ if unmatched. found_delim . is_none ( ) {
1169+ // Encountered `Eof` when lexing blocks. Do not recover here to avoid knockdown
1170+ // errors which would be emitted elsewhere in the parser and let other error
1171+ // recovery consume the rest of the file.
1172+ Err ( err)
1173+ } else {
1174+ err. emit ( ) ;
1175+ self . expected_tokens . clear ( ) ; // Reduce the number of errors.
1176+ Ok ( true )
1177+ }
11601178 }
11611179 _ => Err ( err) ,
11621180 }
11631181 }
11641182
11651183 /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid.
11661184 pub ( super ) fn eat_bad_pub ( & mut self ) {
1167- if self . token . is_keyword ( kw:: Pub ) {
1185+ // When `unclosed_delims` is populated, it means that the code being parsed is already
1186+ // quite malformed, which might mean that, for example, a pub struct definition could be
1187+ // parsed as being a trait item, which is invalid and this error would trigger
1188+ // unconditionally, resulting in misleading diagnostics. Because of this, we only attempt
1189+ // this nice to have recovery for code that is otherwise well formed.
1190+ if self . token . is_keyword ( kw:: Pub ) && self . unclosed_delims . is_empty ( ) {
11681191 match self . parse_visibility ( false ) {
11691192 Ok ( vis) => {
11701193 self . diagnostic ( )
@@ -1422,15 +1445,26 @@ impl<'a> Parser<'a> {
14221445 Ok ( param)
14231446 }
14241447
1425- pub ( super ) fn consume_block ( & mut self , delim : token:: DelimToken ) {
1448+ pub ( super ) fn consume_block (
1449+ & mut self ,
1450+ delim : token:: DelimToken ,
1451+ consume_close : ConsumeClosingDelim ,
1452+ ) {
14261453 let mut brace_depth = 0 ;
14271454 loop {
14281455 if self . eat ( & token:: OpenDelim ( delim) ) {
14291456 brace_depth += 1 ;
1430- } else if self . eat ( & token:: CloseDelim ( delim) ) {
1457+ } else if self . check ( & token:: CloseDelim ( delim) ) {
14311458 if brace_depth == 0 {
1459+ if let ConsumeClosingDelim :: Yes = consume_close {
1460+ // Some of the callers of this method expect to be able to parse the
1461+ // closing delimiter themselves, so we leave it alone. Otherwise we advance
1462+ // the parser.
1463+ self . bump ( ) ;
1464+ }
14321465 return ;
14331466 } else {
1467+ self . bump ( ) ;
14341468 brace_depth -= 1 ;
14351469 continue ;
14361470 }
0 commit comments