@@ -268,8 +268,8 @@ pub struct Parser<'a> {
268
268
/// Used to determine the path to externally loaded source files
269
269
pub filename : Option < String > ,
270
270
pub mod_path_stack : Vec < InternedString > ,
271
- /// Stack of spans of open delimiters. Used for error message.
272
- pub open_braces : Vec < Span > ,
271
+ /// Stack of open delimiters and their spans . Used for error message.
272
+ pub open_braces : Vec < ( token :: DelimToken , Span ) > ,
273
273
/// Flag if this parser "owns" the directory that it is currently parsing
274
274
/// in. This will affect how nested files are looked up.
275
275
pub owns_directory : bool ,
@@ -895,7 +895,7 @@ impl<'a> Parser<'a> {
895
895
sep : SeqSep ,
896
896
f : F )
897
897
-> Vec < T >
898
- where F : FnMut ( & mut Parser < ' a > ) -> PResult < ' a , T > ,
898
+ where F : FnMut ( & mut Parser < ' a > ) -> PResult < ' a , T >
899
899
{
900
900
self . parse_seq_to_before_tokens ( & [ ket] , sep, f, |mut e| e. emit ( ) )
901
901
}
@@ -2755,8 +2755,8 @@ impl<'a> Parser<'a> {
2755
2755
let mut err: DiagnosticBuilder < ' a > =
2756
2756
self . diagnostic ( ) . struct_span_err ( self . span ,
2757
2757
"this file contains an un-closed delimiter" ) ;
2758
- for sp in & self . open_braces {
2759
- err. span_help ( * sp, "did you mean to close this delimiter?" ) ;
2758
+ for & ( _ , sp ) in & self . open_braces {
2759
+ err. span_help ( sp, "did you mean to close this delimiter?" ) ;
2760
2760
}
2761
2761
2762
2762
Err ( err)
@@ -2766,23 +2766,66 @@ impl<'a> Parser<'a> {
2766
2766
let pre_span = self . span ;
2767
2767
2768
2768
// Parse the open delimiter.
2769
- self . open_braces . push ( self . span ) ;
2769
+ self . open_braces . push ( ( delim , self . span ) ) ;
2770
2770
let open_span = self . span ;
2771
2771
self . bump ( ) ;
2772
2772
2773
- // Parse the token trees within the delimiters
2774
- let tts = self . parse_seq_to_before_end ( & token:: CloseDelim ( delim) ,
2775
- SeqSep :: none ( ) ,
2776
- |p| p. parse_token_tree ( ) ) ;
2773
+ // Parse the token trees within the delimiters.
2774
+ // We stop at any delimiter so we can try to recover if the user
2775
+ // uses an incorrect delimiter.
2776
+ let tts = self . parse_seq_to_before_tokens ( & [ & token:: CloseDelim ( token:: Brace ) ,
2777
+ & token:: CloseDelim ( token:: Paren ) ,
2778
+ & token:: CloseDelim ( token:: Bracket ) ] ,
2779
+ SeqSep :: none ( ) ,
2780
+ |p| p. parse_token_tree ( ) ,
2781
+ |mut e| e. emit ( ) ) ;
2777
2782
2778
- // Parse the close delimiter.
2779
2783
let close_span = self . span ;
2780
- self . bump ( ) ;
2781
- self . open_braces . pop ( ) . unwrap ( ) ;
2782
-
2783
2784
// Expand to cover the entire delimited token tree
2784
2785
let span = Span { hi : close_span. hi , ..pre_span } ;
2785
2786
2787
+ match self . token {
2788
+ // Correct delmiter.
2789
+ token:: CloseDelim ( d) if d == delim => {
2790
+ self . open_braces . pop ( ) . unwrap ( ) ;
2791
+
2792
+ // Parse the close delimiter.
2793
+ self . bump ( ) ;
2794
+ }
2795
+ // Incorect delimiter.
2796
+ token:: CloseDelim ( other) => {
2797
+ let token_str = self . this_token_to_string ( ) ;
2798
+ let mut err = self . diagnostic ( ) . struct_span_err ( self . span ,
2799
+ & format ! ( "incorrect close delimiter: `{}`" , token_str) ) ;
2800
+ // This is a conservative error: only report the last unclosed delimiter.
2801
+ // The previous unclosed delimiters could actually be closed! The parser
2802
+ // just hasn't gotten to them yet.
2803
+ if let Some ( & ( _, sp) ) = self . open_braces . last ( ) {
2804
+ err. span_note ( sp, "unclosed delimiter" ) ;
2805
+ } ;
2806
+ err. emit ( ) ;
2807
+
2808
+ self . open_braces . pop ( ) . unwrap ( ) ;
2809
+
2810
+ // If the incorrect delimter matches an earlier opening
2811
+ // delimiter, then don't consume it (it can be used to
2812
+ // close the earlier one)Otherwise, consume it.
2813
+ // E.g., we try to recover from:
2814
+ // fn foo() {
2815
+ // bar(baz(
2816
+ // } // Incorrect delimiter but matches the earlier `{`
2817
+ if !self . open_braces . iter ( ) . any ( |& ( b, _) | b == other) {
2818
+ self . bump ( ) ;
2819
+ }
2820
+ }
2821
+ token:: Eof => {
2822
+ // Silently recover, the EOF token will be seen again
2823
+ // and an error emitted then. Thus we don't pop from
2824
+ // self.open_braces here.
2825
+ } ,
2826
+ _ => unreachable ! ( ) ,
2827
+ }
2828
+
2786
2829
Ok ( TokenTree :: Delimited ( span, Rc :: new ( Delimited {
2787
2830
delim : delim,
2788
2831
open_span : open_span,
@@ -2798,17 +2841,7 @@ impl<'a> Parser<'a> {
2798
2841
maybe_whole ! ( deref self , NtTT ) ;
2799
2842
match self . token {
2800
2843
token:: CloseDelim ( _) => {
2801
- let token_str = self . this_token_to_string ( ) ;
2802
- let mut err = self . diagnostic ( ) . struct_span_err ( self . span ,
2803
- & format ! ( "incorrect close delimiter: `{}`" , token_str) ) ;
2804
- // This is a conservative error: only report the last unclosed delimiter.
2805
- // The previous unclosed delimiters could actually be closed! The parser
2806
- // just hasn't gotten to them yet.
2807
- if let Some ( & sp) = self . open_braces . last ( ) {
2808
- err. span_note ( sp, "unclosed delimiter" ) ;
2809
- } ;
2810
-
2811
- Err ( err)
2844
+ panic ! ( "should have been caught above" ) ;
2812
2845
} ,
2813
2846
/* we ought to allow different depths of unquotation */
2814
2847
token:: Dollar | token:: SubstNt ( ..) if self . quote_depth > 0 => {
0 commit comments