@@ -2149,7 +2149,27 @@ impl<'a> Parser<'a> {
2149
2149
enable_warning : bool )
2150
2150
-> PResult < ' a , ( ) > {
2151
2151
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) ;
2153
2173
2154
2174
if self . is_import_coupler ( ) || !self . eat ( & token:: ModSep ) {
2155
2175
return Ok ( ( ) ) ;
@@ -2757,7 +2777,7 @@ impl<'a> Parser<'a> {
2757
2777
// Assuming we have just parsed `.`, continue parsing into an expression.
2758
2778
fn parse_dot_suffix ( & mut self , self_arg : P < Expr > , lo : Span ) -> PResult < ' a , P < Expr > > {
2759
2779
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 ) ) ;
2761
2781
2762
2782
Ok ( match self . token {
2763
2783
token:: OpenDelim ( token:: Paren ) => {
@@ -2793,15 +2813,19 @@ impl<'a> Parser<'a> {
2793
2813
/// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
2794
2814
/// ^^ help: remove extra angle brackets
2795
2815
/// ```
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
2798
2818
// cases:
2799
2819
//
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)
2802
2825
//
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>`.
2805
2829
2806
2830
// We only care about trailing angle brackets if we previously parsed angle bracket
2807
2831
// arguments. This helps stop us incorrectly suggesting that extra angle brackets be
@@ -2836,43 +2860,47 @@ impl<'a> Parser<'a> {
2836
2860
// actual operators and not trailing characters - ie `x.foo >> 3`).
2837
2861
let mut position = 0 ;
2838
2862
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.
2841
2866
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
+ } ) {
2851
2880
position += 1 ;
2852
2881
}
2853
2882
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.
2856
2884
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,
2859
2887
) ;
2860
- if !encountered_gt && number_of_shr < 1 {
2888
+ if number_of_gt < 1 && number_of_shr < 1 {
2861
2889
return ;
2862
2890
}
2863
2891
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
2868
2899
// 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 ] ) ;
2870
2901
let span = lo. until ( self . span ) ;
2871
2902
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 ;
2876
2904
self . diagnostic ( )
2877
2905
. struct_span_err (
2878
2906
span,
0 commit comments