@@ -2149,7 +2149,27 @@ impl<'a> Parser<'a> {
21492149 enable_warning : bool )
21502150 -> PResult < ' a , ( ) > {
21512151 loop {
2152- segments. push ( self . parse_path_segment ( style, enable_warning) ?) ;
2152+ let segment = self . parse_path_segment ( style, enable_warning) ?;
2153+ if style == PathStyle :: Expr {
2154+ // In order to check for trailing angle brackets, we must have finished
2155+ // recursing (`parse_path_segment` can indirectly call this function),
2156+ // that is, the next token must be the highlighted part of the below example:
2157+ //
2158+ // `Foo::<Bar as Baz<T>>::Qux`
2159+ // ^ here
2160+ //
2161+ // As opposed to the below highlight (if we had only finished the first
2162+ // recursion):
2163+ //
2164+ // `Foo::<Bar as Baz<T>>::Qux`
2165+ // ^ here
2166+ //
2167+ // `PathStyle::Expr` is only provided at the root invocation and never in
2168+ // `parse_path_segment` to recurse and therefore can be checked to maintain
2169+ // this invariant.
2170+ self . check_trailing_angle_brackets ( & segment, token:: ModSep ) ;
2171+ }
2172+ segments. push ( segment) ;
21532173
21542174 if self . is_import_coupler ( ) || !self . eat ( & token:: ModSep ) {
21552175 return Ok ( ( ) ) ;
@@ -2757,7 +2777,7 @@ impl<'a> Parser<'a> {
27572777 // Assuming we have just parsed `.`, continue parsing into an expression.
27582778 fn parse_dot_suffix ( & mut self , self_arg : P < Expr > , lo : Span ) -> PResult < ' a , P < Expr > > {
27592779 let segment = self . parse_path_segment ( PathStyle :: Expr , true ) ?;
2760- self . check_trailing_angle_brackets ( & segment) ;
2780+ self . check_trailing_angle_brackets ( & segment, token :: OpenDelim ( token :: Paren ) ) ;
27612781
27622782 Ok ( match self . token {
27632783 token:: OpenDelim ( token:: Paren ) => {
@@ -2793,15 +2813,19 @@ impl<'a> Parser<'a> {
27932813 /// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
27942814 /// ^^ help: remove extra angle brackets
27952815 /// ```
2796- fn check_trailing_angle_brackets ( & mut self , segment : & PathSegment ) {
2797- // This function is intended to be invoked from `parse_dot_suffix` where there are two
2816+ fn check_trailing_angle_brackets ( & mut self , segment : & PathSegment , end : token :: Token ) {
2817+ // This function is intended to be invoked after parsing a path segment where there are two
27982818 // cases:
27992819 //
2800- // - A field access (eg. `x.foo`)
2801- // - A method call (eg. `x.foo()`)
2820+ // 1. A specific token is expected after the path segment.
2821+ // eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
2822+ // `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
2823+ // 2. No specific token is expected after the path segment.
2824+ // eg. `x.foo` (field access)
28022825 //
2803- // This function is called after parsing `.foo` and before parsing any parenthesis (if
2804- // present). This includes any angle bracket arguments, such as `.foo::<u32>`.
2826+ // This function is called after parsing `.foo` and before parsing the token `end` (if
2827+ // present). This includes any angle bracket arguments, such as `.foo::<u32>` or
2828+ // `Foo::<Bar>`.
28052829
28062830 // We only care about trailing angle brackets if we previously parsed angle bracket
28072831 // arguments. This helps stop us incorrectly suggesting that extra angle brackets be
@@ -2836,43 +2860,47 @@ impl<'a> Parser<'a> {
28362860 // actual operators and not trailing characters - ie `x.foo >> 3`).
28372861 let mut position = 0 ;
28382862
2839- // The first tokens we will encounter are shift right tokens (`>>`) since pairs of `>`
2840- // characters will have been grouped together by the tokenizer.
2863+ // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
2864+ // many of each (so we can correctly pluralize our error messages) and continue to
2865+ // advance.
28412866 let mut number_of_shr = 0 ;
2842- while self . look_ahead ( position, |t| * t == token:: BinOp ( token:: BinOpToken :: Shr ) ) {
2843- number_of_shr += 1 ;
2844- position += 1 ;
2845- }
2846-
2847- // Afterwards, there will be at most one `>` character remaining (more than one and it'd
2848- // have shown up as a `>>`).
2849- let encountered_gt = self . look_ahead ( position, |t| * t == token:: Gt ) ;
2850- if encountered_gt {
2867+ let mut number_of_gt = 0 ;
2868+ while self . look_ahead ( position, |t| {
2869+ trace ! ( "check_trailing_angle_brackets: t={:?}" , t) ;
2870+ if * t == token:: BinOp ( token:: BinOpToken :: Shr ) {
2871+ number_of_shr += 1 ;
2872+ true
2873+ } else if * t == token:: Gt {
2874+ number_of_gt += 1 ;
2875+ true
2876+ } else {
2877+ false
2878+ }
2879+ } ) {
28512880 position += 1 ;
28522881 }
28532882
2854- // If we didn't find any trailing `>>` characters or a trailing `>`, then we have
2855- // nothing to error about.
2883+ // If we didn't find any trailing `>` characters, then we have nothing to error about.
28562884 debug ! (
2857- "check_trailing_angle_brackets: encountered_gt ={:?} number_of_shr={:?}" ,
2858- encountered_gt , number_of_shr,
2885+ "check_trailing_angle_brackets: number_of_gt ={:?} number_of_shr={:?}" ,
2886+ number_of_gt , number_of_shr,
28592887 ) ;
2860- if !encountered_gt && number_of_shr < 1 {
2888+ if number_of_gt < 1 && number_of_shr < 1 {
28612889 return ;
28622890 }
28632891
2864- // Finally, double check that we have a left parenthesis next as otherwise this is the
2865- // field case.
2866- if self . look_ahead ( position, |t| * t == token:: OpenDelim ( token:: Paren ) ) {
2867- // Eat from where we started until the left parenthesis so that parsing can continue
2892+ // Finally, double check that we have our end token as otherwise this is the
2893+ // second case.
2894+ if self . look_ahead ( position, |t| {
2895+ trace ! ( "check_trailing_angle_brackets: t={:?}" , t) ;
2896+ * t == end
2897+ } ) {
2898+ // Eat from where we started until the end token so that parsing can continue
28682899 // as if we didn't have those extra angle brackets.
2869- self . eat_to_tokens ( & [ & token :: OpenDelim ( token :: Paren ) ] ) ;
2900+ self . eat_to_tokens ( & [ & end ] ) ;
28702901 let span = lo. until ( self . span ) ;
28712902
2872- // We needn't check `encountered_gt` to determine if we should pluralize "bracket".
2873- // `encountered_gt` can only represent a single `>` character, if `number_of_shr >= 1`
2874- // then there is either `>>` or `>>>` - in either case a plural is warranted.
2875- let plural = number_of_shr >= 1 ;
2903+ let plural = number_of_gt > 1 || number_of_shr >= 1 ;
28762904 self . diagnostic ( )
28772905 . struct_span_err (
28782906 span,
0 commit comments