@@ -150,7 +150,7 @@ fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
150
150
lhs
151
151
}
152
152
153
- #[ derive( PartialEq ) ]
153
+ #[ derive( Clone , PartialEq ) ]
154
154
enum PrevTokenKind {
155
155
DocComment ,
156
156
Comma ,
@@ -162,6 +162,7 @@ enum PrevTokenKind {
162
162
163
163
/* ident is handled by common.rs */
164
164
165
+ #[ derive( Clone ) ]
165
166
pub struct Parser < ' a > {
166
167
pub sess : & ' a ParseSess ,
167
168
/// the current token:
@@ -193,11 +194,13 @@ pub struct Parser<'a> {
193
194
}
194
195
195
196
197
+ #[ derive( Clone ) ]
196
198
struct TokenCursor {
197
199
frame : TokenCursorFrame ,
198
200
stack : Vec < TokenCursorFrame > ,
199
201
}
200
202
203
+ #[ derive( Clone ) ]
201
204
struct TokenCursorFrame {
202
205
delim : token:: DelimToken ,
203
206
span : Span ,
@@ -397,6 +400,7 @@ impl Error {
397
400
}
398
401
}
399
402
403
+ #[ derive( Debug ) ]
400
404
pub enum LhsExpr {
401
405
NotYetParsed ,
402
406
AttributesParsed ( ThinVec < Attribute > ) ,
@@ -1721,7 +1725,7 @@ impl<'a> Parser<'a> {
1721
1725
1722
1726
let segments = match mode {
1723
1727
PathStyle :: Type => {
1724
- self . parse_path_segments_without_colons ( ) ?
1728
+ self . parse_path_segments_without_colons ( true ) ?
1725
1729
}
1726
1730
PathStyle :: Expr => {
1727
1731
self . parse_path_segments_with_colons ( ) ?
@@ -1742,6 +1746,16 @@ impl<'a> Parser<'a> {
1742
1746
/// bounds are permitted and whether `::` must precede type parameter
1743
1747
/// groups.
1744
1748
pub fn parse_path ( & mut self , mode : PathStyle ) -> PResult < ' a , ast:: Path > {
1749
+ self . parse_path_common ( mode, true )
1750
+ }
1751
+
1752
+ pub fn parse_path_without_generics ( & mut self , mode : PathStyle ) -> PResult < ' a , ast:: Path > {
1753
+ self . parse_path_common ( mode, false )
1754
+ }
1755
+
1756
+ fn parse_path_common ( & mut self , mode : PathStyle , parse_generics : bool )
1757
+ -> PResult < ' a , ast:: Path >
1758
+ {
1745
1759
maybe_whole ! ( self , NtPath , |x| x) ;
1746
1760
1747
1761
let lo = self . meta_var_span . unwrap_or ( self . span ) ;
@@ -1752,7 +1766,7 @@ impl<'a> Parser<'a> {
1752
1766
// A bound set is a set of type parameter bounds.
1753
1767
let mut segments = match mode {
1754
1768
PathStyle :: Type => {
1755
- self . parse_path_segments_without_colons ( ) ?
1769
+ self . parse_path_segments_without_colons ( parse_generics ) ?
1756
1770
}
1757
1771
PathStyle :: Expr => {
1758
1772
self . parse_path_segments_with_colons ( ) ?
@@ -1797,7 +1811,9 @@ impl<'a> Parser<'a> {
1797
1811
/// - `a::b<T,U>::c<V,W>`
1798
1812
/// - `a::b<T,U>::c(V) -> W`
1799
1813
/// - `a::b<T,U>::c(V)`
1800
- pub fn parse_path_segments_without_colons ( & mut self ) -> PResult < ' a , Vec < PathSegment > > {
1814
+ pub fn parse_path_segments_without_colons ( & mut self , parse_generics : bool )
1815
+ -> PResult < ' a , Vec < PathSegment > >
1816
+ {
1801
1817
let mut segments = Vec :: new ( ) ;
1802
1818
loop {
1803
1819
// First, parse an identifier.
@@ -1816,7 +1832,7 @@ impl<'a> Parser<'a> {
1816
1832
}
1817
1833
1818
1834
// Parse types, optionally.
1819
- let parameters = if self . eat_lt ( ) {
1835
+ let parameters = if parse_generics && self . eat_lt ( ) {
1820
1836
let ( lifetimes, types, bindings) = self . parse_generic_args ( ) ?;
1821
1837
self . expect_gt ( ) ?;
1822
1838
ast:: AngleBracketedParameterData {
@@ -2795,8 +2811,9 @@ impl<'a> Parser<'a> {
2795
2811
}
2796
2812
// Special cases:
2797
2813
if op == AssocOp :: As {
2798
- let rhs = self . parse_ty_no_plus ( ) ?;
2799
- lhs = self . mk_expr ( lhs_span. to ( rhs. span ) , ExprKind :: Cast ( lhs, rhs) , ThinVec :: new ( ) ) ;
2814
+ // Save the state of the parser before parsing type normally, in case there is a
2815
+ // LessThan comparison after this cast.
2816
+ lhs = self . parse_assoc_op_as ( lhs, lhs_span) ?;
2800
2817
continue
2801
2818
} else if op == AssocOp :: Colon {
2802
2819
let rhs = self . parse_ty_no_plus ( ) ?;
@@ -2894,11 +2911,74 @@ impl<'a> Parser<'a> {
2894
2911
Ok ( lhs)
2895
2912
}
2896
2913
2914
+ fn parse_assoc_op_as ( & mut self , lhs : P < Expr > , lhs_span : Span ) -> PResult < ' a , P < Expr > > {
2915
+ let rp = self . clone ( ) ;
2916
+ match self . parse_ty_no_plus ( ) {
2917
+ Ok ( rhs) => {
2918
+ Ok ( self . mk_expr ( lhs_span. to ( rhs. span ) ,
2919
+ ExprKind :: Cast ( lhs, rhs) ,
2920
+ ThinVec :: new ( ) ) )
2921
+ }
2922
+ Err ( mut err) => {
2923
+ let rp_err = self . clone ( ) ;
2924
+ let sp = rp_err. span . clone ( ) ;
2925
+
2926
+ // Rewind to before attempting to parse the type with generics, to get
2927
+ // arround #22644.
2928
+ mem:: replace ( self , rp) ;
2929
+ let lo = self . span ;
2930
+ match self . parse_path_without_generics ( PathStyle :: Type ) {
2931
+ Ok ( path) => {
2932
+ // Successfully parsed the type leaving a `<` yet to parse
2933
+ err. cancel ( ) ;
2934
+ let codemap = self . sess . codemap ( ) ;
2935
+ let suggestion_span = lhs_span. to ( self . prev_span ) ;
2936
+ let suggestion = match codemap. span_to_snippet ( suggestion_span) {
2937
+ Ok ( lstring) => format ! ( "({})" , lstring) ,
2938
+ _ => format ! ( "(<expression> as <type>)" )
2939
+ } ;
2940
+ let warn_message = match codemap. span_to_snippet ( self . prev_span ) {
2941
+ Ok ( lstring) => format ! ( "`{}`" , lstring) ,
2942
+ _ => "a type" . to_string ( ) ,
2943
+ } ;
2944
+ let msg = format ! ( "`<` is interpreted as a start of generic \
2945
+ arguments for {}, not a comparison",
2946
+ warn_message) ;
2947
+ let mut err = self . sess . span_diagnostic . struct_span_err ( sp, & msg) ;
2948
+ err. span_label ( sp, "interpreted as generic argument" ) ;
2949
+ err. span_label ( self . span , "not interpreted as comparison" ) ;
2950
+ err. span_suggestion ( suggestion_span,
2951
+ "if you want to compare the casted value then write:" ,
2952
+ suggestion) ;
2953
+ err. emit ( ) ;
2954
+
2955
+ let path = TyKind :: Path ( None , path) ;
2956
+ let span = lo. to ( self . prev_span ) ;
2957
+ let rhs = P ( Ty { node : path, span : span, id : ast:: DUMMY_NODE_ID } ) ;
2958
+ // Letting the parser accept the recovered type to avoid further errors,
2959
+ // but the code will still not compile due to the error emitted above.
2960
+ Ok ( self . mk_expr ( lhs_span. to ( rhs. span ) ,
2961
+ ExprKind :: Cast ( lhs, rhs) ,
2962
+ ThinVec :: new ( ) ) )
2963
+ }
2964
+ Err ( mut path_err) => {
2965
+ // Still couldn't parse, return original error and parser state
2966
+ path_err. cancel ( ) ;
2967
+ mem:: replace ( self , rp_err) ;
2968
+ Err ( err)
2969
+ }
2970
+ }
2971
+ }
2972
+ }
2973
+ }
2974
+
2897
2975
/// Produce an error if comparison operators are chained (RFC #558).
2898
2976
/// We only need to check lhs, not rhs, because all comparison ops
2899
2977
/// have same precedence and are left-associative
2900
2978
fn check_no_chained_comparison ( & mut self , lhs : & Expr , outer_op : & AssocOp ) {
2901
- debug_assert ! ( outer_op. is_comparison( ) ) ;
2979
+ debug_assert ! ( outer_op. is_comparison( ) ,
2980
+ "check_no_chained_comparison: {:?} is not comparison" ,
2981
+ outer_op) ;
2902
2982
match lhs. node {
2903
2983
ExprKind :: Binary ( op, _, _) if op. node . is_comparison ( ) => {
2904
2984
// respan to include both operators
@@ -2922,7 +3002,9 @@ impl<'a> Parser<'a> {
2922
3002
fn parse_prefix_range_expr ( & mut self ,
2923
3003
already_parsed_attrs : Option < ThinVec < Attribute > > )
2924
3004
-> PResult < ' a , P < Expr > > {
2925
- debug_assert ! ( self . token == token:: DotDot || self . token == token:: DotDotDot ) ;
3005
+ debug_assert ! ( self . token == token:: DotDot || self . token == token:: DotDotDot ,
3006
+ "parse_prefix_range_expr: token {:?} is not DotDot or DotDotDot" ,
3007
+ self . token) ;
2926
3008
let tok = self . token . clone ( ) ;
2927
3009
let attrs = self . parse_or_use_outer_attributes ( already_parsed_attrs) ?;
2928
3010
let lo = self . span ;
0 commit comments