@@ -3736,20 +3736,15 @@ impl<'a> Parser<'a> {
3736
3736
|| self . token . can_begin_literal_or_bool ( ) // e.g. `42`.
3737
3737
}
3738
3738
3739
- // helper function to decide whether to parse as ident binding or to try to do
3740
- // something more complex like range patterns
3739
+ // Helper function to decide whether to parse as ident binding
3740
+ // or to try to do something more complex like range patterns.
3741
3741
fn parse_as_ident ( & mut self ) -> bool {
3742
3742
self . look_ahead ( 1 , |t| match t. kind {
3743
3743
token:: OpenDelim ( token:: Paren ) | token:: OpenDelim ( token:: Brace ) |
3744
- token:: DotDotDot | token:: DotDotEq | token:: ModSep | token:: Not => Some ( false ) ,
3745
- // ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the
3746
- // range pattern branch
3747
- token:: DotDot => None ,
3748
- _ => Some ( true ) ,
3749
- } ) . unwrap_or_else ( || self . look_ahead ( 2 , |t| match t. kind {
3750
- token:: Comma | token:: CloseDelim ( token:: Bracket ) => true ,
3751
- _ => false ,
3752
- } ) )
3744
+ token:: DotDotDot | token:: DotDotEq | token:: DotDot |
3745
+ token:: ModSep | token:: Not => false ,
3746
+ _ => true ,
3747
+ } )
3753
3748
}
3754
3749
3755
3750
/// Parse a parentesized comma separated sequence of patterns until `delim` is reached.
@@ -3828,6 +3823,33 @@ impl<'a> Parser<'a> {
3828
3823
Ok ( PatKind :: Range ( begin, end, respan ( lo, re) ) )
3829
3824
}
3830
3825
3826
+ /// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern or recover
3827
+ /// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively.
3828
+ fn parse_pat_range_end_opt ( & mut self , begin : & Expr , form : & str ) -> PResult < ' a , P < Expr > > {
3829
+ if self . is_pat_range_end_start ( ) {
3830
+ // Parsing e.g. `X..=Y`.
3831
+ self . parse_pat_range_end ( )
3832
+ } else {
3833
+ // Parsing e.g. `X..`.
3834
+ let range_span = begin. span . to ( self . prev_span ) ;
3835
+
3836
+ self . diagnostic ( )
3837
+ . struct_span_err (
3838
+ range_span,
3839
+ & format ! ( "`X{}` range patterns are not supported" , form) ,
3840
+ )
3841
+ . span_suggestion (
3842
+ range_span,
3843
+ "try using the maximum value for the type" ,
3844
+ format ! ( "{}{}MAX" , pprust:: expr_to_string( & begin) , form) ,
3845
+ Applicability :: HasPlaceholders ,
3846
+ )
3847
+ . emit ( ) ;
3848
+
3849
+ Ok ( self . mk_expr ( range_span, ExprKind :: Err , ThinVec :: new ( ) ) )
3850
+ }
3851
+ }
3852
+
3831
3853
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
3832
3854
/// allowed).
3833
3855
fn parse_pat_with_range_pat (
@@ -3943,10 +3965,10 @@ impl<'a> Parser<'a> {
3943
3965
pat = PatKind :: Mac ( mac) ;
3944
3966
}
3945
3967
token:: DotDotDot | token:: DotDotEq | token:: DotDot => {
3946
- let end_kind = match self . token . kind {
3947
- token:: DotDot => RangeEnd :: Excluded ,
3948
- token:: DotDotDot => RangeEnd :: Included ( RangeSyntax :: DotDotDot ) ,
3949
- token:: DotDotEq => RangeEnd :: Included ( RangeSyntax :: DotDotEq ) ,
3968
+ let ( end_kind, form ) = match self . token . kind {
3969
+ token:: DotDot => ( RangeEnd :: Excluded , ".." ) ,
3970
+ token:: DotDotDot => ( RangeEnd :: Included ( RangeSyntax :: DotDotDot ) , "..." ) ,
3971
+ token:: DotDotEq => ( RangeEnd :: Included ( RangeSyntax :: DotDotEq ) , "..=" ) ,
3950
3972
_ => panic ! ( "can only parse `..`/`...`/`..=` for ranges \
3951
3973
(checked above)") ,
3952
3974
} ;
@@ -3955,7 +3977,7 @@ impl<'a> Parser<'a> {
3955
3977
let span = lo. to ( self . prev_span ) ;
3956
3978
let begin = self . mk_expr ( span, ExprKind :: Path ( qself, path) , ThinVec :: new ( ) ) ;
3957
3979
self . bump ( ) ;
3958
- let end = self . parse_pat_range_end ( ) ?;
3980
+ let end = self . parse_pat_range_end_opt ( & begin , form ) ?;
3959
3981
pat = PatKind :: Range ( begin, end, respan ( op_span, end_kind) ) ;
3960
3982
}
3961
3983
token:: OpenDelim ( token:: Brace ) => {
@@ -3995,17 +4017,17 @@ impl<'a> Parser<'a> {
3995
4017
let op_span = self . token . span ;
3996
4018
if self . check ( & token:: DotDot ) || self . check ( & token:: DotDotEq ) ||
3997
4019
self . check ( & token:: DotDotDot ) {
3998
- let end_kind = if self . eat ( & token:: DotDotDot ) {
3999
- RangeEnd :: Included ( RangeSyntax :: DotDotDot )
4020
+ let ( end_kind, form ) = if self . eat ( & token:: DotDotDot ) {
4021
+ ( RangeEnd :: Included ( RangeSyntax :: DotDotDot ) , "..." )
4000
4022
} else if self . eat ( & token:: DotDotEq ) {
4001
- RangeEnd :: Included ( RangeSyntax :: DotDotEq )
4023
+ ( RangeEnd :: Included ( RangeSyntax :: DotDotEq ) , "..=" )
4002
4024
} else if self . eat ( & token:: DotDot ) {
4003
- RangeEnd :: Excluded
4025
+ ( RangeEnd :: Excluded , ".." )
4004
4026
} else {
4005
4027
panic ! ( "impossible case: we already matched \
4006
4028
on a range-operator token")
4007
4029
} ;
4008
- let end = self . parse_pat_range_end ( ) ?;
4030
+ let end = self . parse_pat_range_end_opt ( & begin , form ) ?;
4009
4031
pat = PatKind :: Range ( begin, end, respan ( op_span, end_kind) )
4010
4032
} else {
4011
4033
pat = PatKind :: Lit ( begin) ;
0 commit comments