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