@@ -243,6 +243,12 @@ pub struct Parser<'a> {
243243 desugar_doc_comments : bool ,
244244 /// Whether we should configure out of line modules as we parse.
245245 pub cfg_mods : bool ,
246+ /// This field is used to keep track of how many left angle brackets we have seen. This is
247+ /// required in order to detect extra leading left angle brackets (`<` characters) and error
248+ /// appropriately.
249+ ///
250+ /// See the comments in the `parse_path_segment` function for more details.
251+ crate unmatched_angle_bracket_count : u32 ,
246252}
247253
248254
@@ -564,6 +570,7 @@ impl<'a> Parser<'a> {
564570 } ,
565571 desugar_doc_comments,
566572 cfg_mods : true ,
573+ unmatched_angle_bracket_count : 0 ,
567574 } ;
568575
569576 let tok = parser. next_tok ( ) ;
@@ -1028,7 +1035,7 @@ impl<'a> Parser<'a> {
10281035 /// starting token.
10291036 fn eat_lt ( & mut self ) -> bool {
10301037 self . expected_tokens . push ( TokenType :: Token ( token:: Lt ) ) ;
1031- match self . token {
1038+ let ate = match self . token {
10321039 token:: Lt => {
10331040 self . bump ( ) ;
10341041 true
@@ -1039,7 +1046,15 @@ impl<'a> Parser<'a> {
10391046 true
10401047 }
10411048 _ => false ,
1049+ } ;
1050+
1051+ if ate {
1052+ // See doc comment for `unmatched_angle_bracket_count`.
1053+ self . unmatched_angle_bracket_count += 1 ;
1054+ debug ! ( "eat_lt: (increment) count={:?}" , self . unmatched_angle_bracket_count) ;
10421055 }
1056+
1057+ ate
10431058 }
10441059
10451060 fn expect_lt ( & mut self ) -> PResult < ' a , ( ) > {
@@ -1055,24 +1070,35 @@ impl<'a> Parser<'a> {
10551070 /// signal an error.
10561071 fn expect_gt ( & mut self ) -> PResult < ' a , ( ) > {
10571072 self . expected_tokens . push ( TokenType :: Token ( token:: Gt ) ) ;
1058- match self . token {
1073+ let ate = match self . token {
10591074 token:: Gt => {
10601075 self . bump ( ) ;
1061- Ok ( ( ) )
1076+ Some ( ( ) )
10621077 }
10631078 token:: BinOp ( token:: Shr ) => {
10641079 let span = self . span . with_lo ( self . span . lo ( ) + BytePos ( 1 ) ) ;
1065- Ok ( self . bump_with ( token:: Gt , span) )
1080+ Some ( self . bump_with ( token:: Gt , span) )
10661081 }
10671082 token:: BinOpEq ( token:: Shr ) => {
10681083 let span = self . span . with_lo ( self . span . lo ( ) + BytePos ( 1 ) ) ;
1069- Ok ( self . bump_with ( token:: Ge , span) )
1084+ Some ( self . bump_with ( token:: Ge , span) )
10701085 }
10711086 token:: Ge => {
10721087 let span = self . span . with_lo ( self . span . lo ( ) + BytePos ( 1 ) ) ;
1073- Ok ( self . bump_with ( token:: Eq , span) )
1088+ Some ( self . bump_with ( token:: Eq , span) )
10741089 }
1075- _ => self . unexpected ( )
1090+ _ => None ,
1091+ } ;
1092+
1093+ match ate {
1094+ Some ( x) => {
1095+ // See doc comment for `unmatched_angle_bracket_count`.
1096+ self . unmatched_angle_bracket_count -= 1 ;
1097+ debug ! ( "expect_gt: (decrement) count={:?}" , self . unmatched_angle_bracket_count) ;
1098+
1099+ Ok ( x)
1100+ } ,
1101+ None => self . unexpected ( ) ,
10761102 }
10771103 }
10781104
@@ -2115,7 +2141,11 @@ impl<'a> Parser<'a> {
21152141 path_span = self . span . to ( self . span ) ;
21162142 }
21172143
2144+ // See doc comment for `unmatched_angle_bracket_count`.
21182145 self . expect ( & token:: Gt ) ?;
2146+ self . unmatched_angle_bracket_count -= 1 ;
2147+ debug ! ( "parse_qpath: (decrement) count={:?}" , self . unmatched_angle_bracket_count) ;
2148+
21192149 self . expect ( & token:: ModSep ) ?;
21202150
21212151 let qself = QSelf { ty, path_span, position : path. segments . len ( ) } ;
@@ -2238,9 +2268,15 @@ impl<'a> Parser<'a> {
22382268 }
22392269 let lo = self . span ;
22402270
2271+ // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
2272+ // it isn't, then we reset the unmatched angle bracket count as we're about to start
2273+ // parsing a new path.
2274+ if style == PathStyle :: Expr { self . unmatched_angle_bracket_count = 0 ; }
2275+
22412276 let args = if self . eat_lt ( ) {
22422277 // `<'a, T, A = U>`
2243- let ( args, bindings) = self . parse_generic_args ( ) ?;
2278+ let ( args, bindings) =
2279+ self . parse_generic_args_with_leaning_angle_bracket_recovery ( style, lo) ?;
22442280 self . expect_gt ( ) ?;
22452281 let span = lo. to ( self . prev_span ) ;
22462282 AngleBracketedArgs { args, bindings, span } . into ( )
@@ -5538,6 +5574,152 @@ impl<'a> Parser<'a> {
55385574 }
55395575 }
55405576
5577+ /// Parse generic args (within a path segment) with recovery for extra leading angle brackets.
5578+ /// For the purposes of understanding the parsing logic of generic arguments, this function
5579+ /// can be thought of being the same as just calling `self.parse_generic_args()` if the source
5580+ /// had the correct amount of leading angle brackets.
5581+ ///
5582+ /// ```ignore (diagnostics)
5583+ /// bar::<<<<T as Foo>::Output>();
5584+ /// ^^ help: remove extra angle brackets
5585+ /// ```
5586+ fn parse_generic_args_with_leaning_angle_bracket_recovery (
5587+ & mut self ,
5588+ style : PathStyle ,
5589+ lo : Span ,
5590+ ) -> PResult < ' a , ( Vec < GenericArg > , Vec < TypeBinding > ) > {
5591+ // We need to detect whether there are extra leading left angle brackets and produce an
5592+ // appropriate error and suggestion. This cannot be implemented by looking ahead at
5593+ // upcoming tokens for a matching `>` character - if there are unmatched `<` tokens
5594+ // then there won't be matching `>` tokens to find.
5595+ //
5596+ // To explain how this detection works, consider the following example:
5597+ //
5598+ // ```ignore (diagnostics)
5599+ // bar::<<<<T as Foo>::Output>();
5600+ // ^^ help: remove extra angle brackets
5601+ // ```
5602+ //
5603+ // Parsing of the left angle brackets starts in this function. We start by parsing the
5604+ // `<` token (incrementing the counter of unmatched angle brackets on `Parser` via
5605+ // `eat_lt`):
5606+ //
5607+ // *Upcoming tokens:* `<<<<T as Foo>::Output>;`
5608+ // *Unmatched count:* 1
5609+ // *`parse_path_segment` calls deep:* 0
5610+ //
5611+ // This has the effect of recursing as this function is called if a `<` character
5612+ // is found within the expected generic arguments:
5613+ //
5614+ // *Upcoming tokens:* `<<<T as Foo>::Output>;`
5615+ // *Unmatched count:* 2
5616+ // *`parse_path_segment` calls deep:* 1
5617+ //
5618+ // Eventually we will have recursed until having consumed all of the `<` tokens and
5619+ // this will be reflected in the count:
5620+ //
5621+ // *Upcoming tokens:* `T as Foo>::Output>;`
5622+ // *Unmatched count:* 4
5623+ // `parse_path_segment` calls deep:* 3
5624+ //
5625+ // The parser will continue until reaching the first `>` - this will decrement the
5626+ // unmatched angle bracket count and return to the parent invocation of this function
5627+ // having succeeded in parsing:
5628+ //
5629+ // *Upcoming tokens:* `::Output>;`
5630+ // *Unmatched count:* 3
5631+ // *`parse_path_segment` calls deep:* 2
5632+ //
5633+ // This will continue until the next `>` character which will also return successfully
5634+ // to the parent invocation of this function and decrement the count:
5635+ //
5636+ // *Upcoming tokens:* `;`
5637+ // *Unmatched count:* 2
5638+ // *`parse_path_segment` calls deep:* 1
5639+ //
5640+ // At this point, this function will expect to find another matching `>` character but
5641+ // won't be able to and will return an error. This will continue all the way up the
5642+ // call stack until the first invocation:
5643+ //
5644+ // *Upcoming tokens:* `;`
5645+ // *Unmatched count:* 2
5646+ // *`parse_path_segment` calls deep:* 0
5647+ //
5648+ // In doing this, we have managed to work out how many unmatched leading left angle
5649+ // brackets there are, but we cannot recover as the unmatched angle brackets have
5650+ // already been consumed. To remedy this, we keep a snapshot of the parser state
5651+ // before we do the above. We can then inspect whether we ended up with a parsing error
5652+ // and unmatched left angle brackets and if so, restore the parser state before we
5653+ // consumed any `<` characters to emit an error and consume the erroneous tokens to
5654+ // recover by attempting to parse again.
5655+ //
5656+ // In practice, the recursion of this function is indirect and there will be other
5657+ // locations that consume some `<` characters - as long as we update the count when
5658+ // this happens, it isn't an issue.
5659+
5660+ let is_first_invocation = style == PathStyle :: Expr ;
5661+ // Take a snapshot before attempting to parse - we can restore this later.
5662+ let snapshot = if is_first_invocation {
5663+ Some ( self . clone ( ) )
5664+ } else {
5665+ None
5666+ } ;
5667+
5668+ debug ! ( "parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)" ) ;
5669+ match self . parse_generic_args ( ) {
5670+ Ok ( value) => Ok ( value) ,
5671+ Err ( ref mut e) if is_first_invocation && self . unmatched_angle_bracket_count > 0 => {
5672+ // Cancel error from being unable to find `>`. We know the error
5673+ // must have been this due to a non-zero unmatched angle bracket
5674+ // count.
5675+ e. cancel ( ) ;
5676+
5677+ // Swap `self` with our backup of the parser state before attempting to parse
5678+ // generic arguments.
5679+ let snapshot = mem:: replace ( self , snapshot. unwrap ( ) ) ;
5680+
5681+ debug ! (
5682+ "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
5683+ snapshot.count={:?}",
5684+ snapshot. unmatched_angle_bracket_count,
5685+ ) ;
5686+
5687+ // Eat the unmatched angle brackets.
5688+ for _ in 0 ..snapshot. unmatched_angle_bracket_count {
5689+ self . eat_lt ( ) ;
5690+ }
5691+
5692+ // Make a span over ${unmatched angle bracket count} characters.
5693+ let span = lo. with_hi (
5694+ lo. lo ( ) + BytePos ( snapshot. unmatched_angle_bracket_count )
5695+ ) ;
5696+ let plural = snapshot. unmatched_angle_bracket_count > 1 ;
5697+ self . diagnostic ( )
5698+ . struct_span_err (
5699+ span,
5700+ & format ! (
5701+ "unmatched angle bracket{}" ,
5702+ if plural { "s" } else { "" }
5703+ ) ,
5704+ )
5705+ . span_suggestion_with_applicability (
5706+ span,
5707+ & format ! (
5708+ "remove extra angle bracket{}" ,
5709+ if plural { "s" } else { "" }
5710+ ) ,
5711+ String :: new ( ) ,
5712+ Applicability :: MachineApplicable ,
5713+ )
5714+ . emit ( ) ;
5715+
5716+ // Try again without unmatched angle bracket characters.
5717+ self . parse_generic_args ( )
5718+ } ,
5719+ Err ( e) => Err ( e) ,
5720+ }
5721+ }
5722+
55415723 /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
55425724 /// possibly including trailing comma.
55435725 fn parse_generic_args ( & mut self ) -> PResult < ' a , ( Vec < GenericArg > , Vec < TypeBinding > ) > {
0 commit comments