@@ -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:
@@ -441,15 +442,6 @@ fn dummy_arg(span: Span) -> Arg {
441
442
Arg { ty : P ( ty) , pat : pat, id : ast:: DUMMY_NODE_ID }
442
443
}
443
444
444
- struct RewindPoint {
445
- token : token:: Token ,
446
- span : Span ,
447
- meta_var_span : Option < Span > ,
448
- prev_span : Span ,
449
- token_cursor : TokenCursor ,
450
- expected_tokens : Vec < TokenType > ,
451
- }
452
-
453
445
impl < ' a > Parser < ' a > {
454
446
pub fn new ( sess : & ' a ParseSess ,
455
447
tokens : TokenStream ,
@@ -798,13 +790,6 @@ impl<'a> Parser<'a> {
798
790
}
799
791
}
800
792
801
- fn is_lt ( & mut self ) -> bool {
802
- match self . token {
803
- token:: Lt | token:: BinOp ( token:: Shl ) => true ,
804
- _ => false ,
805
- }
806
- }
807
-
808
793
/// Attempt to consume a `<`. If `<<` is seen, replace it with a single
809
794
/// `<` and continue. If a `<` is not seen, return false.
810
795
///
@@ -1743,7 +1728,7 @@ impl<'a> Parser<'a> {
1743
1728
1744
1729
let segments = match mode {
1745
1730
PathStyle :: Type => {
1746
- self . parse_path_segments_without_colons ( false ) ?
1731
+ self . parse_path_segments_without_colons ( true ) ?
1747
1732
}
1748
1733
PathStyle :: Expr => {
1749
1734
self . parse_path_segments_with_colons ( ) ?
@@ -1764,14 +1749,14 @@ impl<'a> Parser<'a> {
1764
1749
/// bounds are permitted and whether `::` must precede type parameter
1765
1750
/// groups.
1766
1751
pub fn parse_path ( & mut self , mode : PathStyle ) -> PResult < ' a , ast:: Path > {
1767
- self . parse_path_common ( mode, false )
1752
+ self . parse_path_common ( mode, true )
1768
1753
}
1769
1754
1770
1755
pub fn parse_path_without_generics ( & mut self , mode : PathStyle ) -> PResult < ' a , ast:: Path > {
1771
- self . parse_path_common ( mode, true )
1756
+ self . parse_path_common ( mode, false )
1772
1757
}
1773
1758
1774
- fn parse_path_common ( & mut self , mode : PathStyle , dont_parse_generics : bool )
1759
+ fn parse_path_common ( & mut self , mode : PathStyle , parse_generics : bool )
1775
1760
-> PResult < ' a , ast:: Path >
1776
1761
{
1777
1762
maybe_whole ! ( self , NtPath , |x| x) ;
@@ -1784,7 +1769,7 @@ impl<'a> Parser<'a> {
1784
1769
// A bound set is a set of type parameter bounds.
1785
1770
let mut segments = match mode {
1786
1771
PathStyle :: Type => {
1787
- self . parse_path_segments_without_colons ( dont_parse_generics ) ?
1772
+ self . parse_path_segments_without_colons ( parse_generics ) ?
1788
1773
}
1789
1774
PathStyle :: Expr => {
1790
1775
self . parse_path_segments_with_colons ( ) ?
@@ -1829,7 +1814,7 @@ impl<'a> Parser<'a> {
1829
1814
/// - `a::b<T,U>::c<V,W>`
1830
1815
/// - `a::b<T,U>::c(V) -> W`
1831
1816
/// - `a::b<T,U>::c(V)`
1832
- pub fn parse_path_segments_without_colons ( & mut self , dont_parse_generics : bool )
1817
+ pub fn parse_path_segments_without_colons ( & mut self , parse_generics : bool )
1833
1818
-> PResult < ' a , Vec < PathSegment > >
1834
1819
{
1835
1820
let mut segments = Vec :: new ( ) ;
@@ -1850,8 +1835,7 @@ impl<'a> Parser<'a> {
1850
1835
}
1851
1836
1852
1837
// Parse types, optionally.
1853
- let parameters = if self . is_lt ( ) && !dont_parse_generics {
1854
- let _ = self . eat_lt ( ) ;
1838
+ let parameters = if parse_generics && self . eat_lt ( ) {
1855
1839
let ( lifetimes, types, bindings) = self . parse_generic_args ( ) ?;
1856
1840
self . expect_gt ( ) ?;
1857
1841
ast:: AngleBracketedParameterData {
@@ -2832,60 +2816,7 @@ impl<'a> Parser<'a> {
2832
2816
if op == AssocOp :: As {
2833
2817
// Save the state of the parser before parsing type normally, in case there is a
2834
2818
// LessThan comparison after this cast.
2835
- let rp = self . get_rewind_point ( ) ;
2836
- match self . parse_ty_no_plus ( ) {
2837
- Ok ( rhs) => {
2838
- lhs = self . mk_expr ( lhs_span. to ( rhs. span ) ,
2839
- ExprKind :: Cast ( lhs, rhs) , ThinVec :: new ( ) ) ;
2840
- }
2841
- Err ( mut err) => {
2842
- // Rewind to before attempting to parse the type with generics, to get
2843
- // arround #22644.
2844
- let rp_err = self . get_rewind_point ( ) ;
2845
- let sp = rp_err. span . clone ( ) ;
2846
- self . rewind ( rp) ;
2847
- let lo = self . span ;
2848
- let path = match self . parse_path_without_generics ( PathStyle :: Type ) {
2849
- Ok ( path) => {
2850
- // Successfully parsed the type leaving a `<` yet to parse
2851
- err. cancel ( ) ;
2852
- let codemap = self . sess . codemap ( ) ;
2853
- let suggestion_span = lhs_span. to ( self . prev_span ) ;
2854
- let suggestion = match codemap. span_to_snippet ( suggestion_span) {
2855
- Ok ( lstring) => format ! ( "({})" , lstring) ,
2856
- _ => format ! ( "(<expression>)" )
2857
- } ;
2858
- let warn_message = match codemap. span_to_snippet ( self . prev_span ) {
2859
- Ok ( lstring) => format ! ( "`{}`" , lstring) ,
2860
- _ => "a type" . to_string ( ) ,
2861
- } ;
2862
- let msg = format ! ( "`<` is interpreted as a start of generic \
2863
- arguments for {}, not a comparison",
2864
- warn_message) ;
2865
- let mut warn = self . sess . span_diagnostic . struct_span_warn ( sp, & msg) ;
2866
- warn. span_label ( sp, "interpreted as generic argument" ) ;
2867
- warn. span_label ( self . span , "not interpreted as comparison" ) ;
2868
- warn. span_suggestion ( suggestion_span,
2869
- "if you want to compare the casted value \
2870
- then write:",
2871
- suggestion) ;
2872
- warn. emit ( ) ;
2873
- path
2874
- }
2875
- Err ( mut path_err) => {
2876
- // Still couldn't parse, return original error and parser state
2877
- path_err. cancel ( ) ;
2878
- self . rewind ( rp_err) ;
2879
- return Err ( err) ;
2880
- }
2881
- } ;
2882
- let path = TyKind :: Path ( None , path) ;
2883
- let span = lo. to ( self . prev_span ) ;
2884
- let rhs = P ( Ty { node : path, span : span, id : ast:: DUMMY_NODE_ID } ) ;
2885
- lhs = self . mk_expr ( lhs_span. to ( rhs. span ) ,
2886
- ExprKind :: Cast ( lhs, rhs) , ThinVec :: new ( ) ) ;
2887
- }
2888
- } ;
2819
+ lhs = self . parse_assoc_op_as ( lhs, lhs_span) ?;
2889
2820
continue
2890
2821
} else if op == AssocOp :: Colon {
2891
2822
let rhs = self . parse_ty_no_plus ( ) ?;
@@ -2983,6 +2914,67 @@ impl<'a> Parser<'a> {
2983
2914
Ok ( lhs)
2984
2915
}
2985
2916
2917
+ fn parse_assoc_op_as ( & mut self , lhs : P < Expr > , lhs_span : Span ) -> PResult < ' a , P < Expr > > {
2918
+ let rp = self . clone ( ) ;
2919
+ match self . parse_ty_no_plus ( ) {
2920
+ Ok ( rhs) => {
2921
+ Ok ( self . mk_expr ( lhs_span. to ( rhs. span ) ,
2922
+ ExprKind :: Cast ( lhs, rhs) ,
2923
+ ThinVec :: new ( ) ) )
2924
+ }
2925
+ Err ( mut err) => {
2926
+ let rp_err = self . clone ( ) ;
2927
+ let sp = rp_err. span . clone ( ) ;
2928
+
2929
+ // Rewind to before attempting to parse the type with generics, to get
2930
+ // arround #22644.
2931
+ mem:: replace ( self , rp) ;
2932
+ let lo = self . span ;
2933
+ match self . parse_path_without_generics ( PathStyle :: Type ) {
2934
+ Ok ( path) => {
2935
+ // Successfully parsed the type leaving a `<` yet to parse
2936
+ err. cancel ( ) ;
2937
+ let codemap = self . sess . codemap ( ) ;
2938
+ let suggestion_span = lhs_span. to ( self . prev_span ) ;
2939
+ let suggestion = match codemap. span_to_snippet ( suggestion_span) {
2940
+ Ok ( lstring) => format ! ( "({})" , lstring) ,
2941
+ _ => format ! ( "(<expression> as <type>)" )
2942
+ } ;
2943
+ let warn_message = match codemap. span_to_snippet ( self . prev_span ) {
2944
+ Ok ( lstring) => format ! ( "`{}`" , lstring) ,
2945
+ _ => "a type" . to_string ( ) ,
2946
+ } ;
2947
+ let msg = format ! ( "`<` is interpreted as a start of generic \
2948
+ arguments for {}, not a comparison",
2949
+ warn_message) ;
2950
+ let mut err = self . sess . span_diagnostic . struct_span_err ( sp, & msg) ;
2951
+ err. span_label ( sp, "interpreted as generic argument" ) ;
2952
+ err. span_label ( self . span , "not interpreted as comparison" ) ;
2953
+ err. span_suggestion ( suggestion_span,
2954
+ "if you want to compare the casted value then write:" ,
2955
+ suggestion) ;
2956
+ err. emit ( ) ;
2957
+
2958
+ let path = TyKind :: Path ( None , path) ;
2959
+ let span = lo. to ( self . prev_span ) ;
2960
+ let rhs = P ( Ty { node : path, span : span, id : ast:: DUMMY_NODE_ID } ) ;
2961
+ // Letting the parser accept the recovered type to avoid further errors,
2962
+ // but the code will still not compile due to the error emitted above.
2963
+ Ok ( self . mk_expr ( lhs_span. to ( rhs. span ) ,
2964
+ ExprKind :: Cast ( lhs, rhs) ,
2965
+ ThinVec :: new ( ) ) )
2966
+ }
2967
+ Err ( mut path_err) => {
2968
+ // Still couldn't parse, return original error and parser state
2969
+ path_err. cancel ( ) ;
2970
+ mem:: replace ( self , rp_err) ;
2971
+ Err ( err)
2972
+ }
2973
+ }
2974
+ }
2975
+ }
2976
+ }
2977
+
2986
2978
/// Produce an error if comparison operators are chained (RFC #558).
2987
2979
/// We only need to check lhs, not rhs, because all comparison ops
2988
2980
/// have same precedence and are left-associative
@@ -6264,24 +6256,4 @@ impl<'a> Parser<'a> {
6264
6256
_ => Err ( self . fatal ( "expected string literal" ) )
6265
6257
}
6266
6258
}
6267
-
6268
- fn get_rewind_point ( & mut self ) -> RewindPoint {
6269
- RewindPoint {
6270
- token : self . token . clone ( ) ,
6271
- span : self . span ,
6272
- meta_var_span : self . meta_var_span ,
6273
- prev_span : self . prev_span ,
6274
- token_cursor : self . token_cursor . clone ( ) ,
6275
- expected_tokens : self . expected_tokens . clone ( ) ,
6276
- }
6277
- }
6278
-
6279
- fn rewind ( & mut self , rp : RewindPoint ) {
6280
- self . token = rp. token ;
6281
- self . span = rp. span ;
6282
- self . meta_var_span = rp. meta_var_span ;
6283
- self . prev_span = rp. prev_span ;
6284
- self . token_cursor = rp. token_cursor ;
6285
- self . expected_tokens = rp. expected_tokens ;
6286
- }
6287
6259
}
0 commit comments