@@ -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