@@ -3535,122 +3535,6 @@ impl<'a> Parser<'a> {
3535
3535
} ;
3536
3536
}
3537
3537
3538
- // Parses a parenthesized list of patterns like
3539
- // `()`, `(p)`, `(p,)`, `(p, q)`, or `(p, .., q)`. Returns:
3540
- // - a vector of the patterns that were parsed
3541
- // - an option indicating the index of the `..` element
3542
- // - a boolean indicating whether a trailing comma was present.
3543
- // Trailing commas are significant because (p) and (p,) are different patterns.
3544
- fn parse_parenthesized_pat_list ( & mut self ) -> PResult < ' a , ( Vec < P < Pat > > , Option < usize > , bool ) > {
3545
- self . expect ( & token:: OpenDelim ( token:: Paren ) ) ?;
3546
- let result = match self . parse_pat_list ( ) {
3547
- Ok ( result) => result,
3548
- Err ( mut err) => { // recover from parse error in tuple pattern list
3549
- err. emit ( ) ;
3550
- self . consume_block ( token:: Paren ) ;
3551
- return Ok ( ( vec ! [ ] , Some ( 0 ) , false ) ) ;
3552
- }
3553
- } ;
3554
- self . expect ( & token:: CloseDelim ( token:: Paren ) ) ?;
3555
- Ok ( result)
3556
- }
3557
-
3558
- fn parse_pat_list ( & mut self ) -> PResult < ' a , ( Vec < P < Pat > > , Option < usize > , bool ) > {
3559
- let mut fields = Vec :: new ( ) ;
3560
- let mut ddpos = None ;
3561
- let mut prev_dd_sp = None ;
3562
- let mut trailing_comma = false ;
3563
- loop {
3564
- if self . eat ( & token:: DotDot ) {
3565
- if ddpos. is_none ( ) {
3566
- ddpos = Some ( fields. len ( ) ) ;
3567
- prev_dd_sp = Some ( self . prev_span ) ;
3568
- } else {
3569
- // Emit a friendly error, ignore `..` and continue parsing
3570
- let mut err = self . struct_span_err (
3571
- self . prev_span ,
3572
- "`..` can only be used once per tuple or tuple struct pattern" ,
3573
- ) ;
3574
- err. span_label ( self . prev_span , "can only be used once per pattern" ) ;
3575
- if let Some ( sp) = prev_dd_sp {
3576
- err. span_label ( sp, "previously present here" ) ;
3577
- }
3578
- err. emit ( ) ;
3579
- }
3580
- } else if !self . check ( & token:: CloseDelim ( token:: Paren ) ) {
3581
- fields. push ( self . parse_pat ( None ) ?) ;
3582
- } else {
3583
- break
3584
- }
3585
-
3586
- trailing_comma = self . eat ( & token:: Comma ) ;
3587
- if !trailing_comma {
3588
- break
3589
- }
3590
- }
3591
-
3592
- if ddpos == Some ( fields. len ( ) ) && trailing_comma {
3593
- // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
3594
- let msg = "trailing comma is not permitted after `..`" ;
3595
- self . struct_span_err ( self . prev_span , msg)
3596
- . span_label ( self . prev_span , msg)
3597
- . emit ( ) ;
3598
- }
3599
-
3600
- Ok ( ( fields, ddpos, trailing_comma) )
3601
- }
3602
-
3603
- fn parse_pat_vec_elements (
3604
- & mut self ,
3605
- ) -> PResult < ' a , ( Vec < P < Pat > > , Option < P < Pat > > , Vec < P < Pat > > ) > {
3606
- let mut before = Vec :: new ( ) ;
3607
- let mut slice = None ;
3608
- let mut after = Vec :: new ( ) ;
3609
- let mut first = true ;
3610
- let mut before_slice = true ;
3611
-
3612
- while self . token != token:: CloseDelim ( token:: Bracket ) {
3613
- if first {
3614
- first = false ;
3615
- } else {
3616
- self . expect ( & token:: Comma ) ?;
3617
-
3618
- if self . token == token:: CloseDelim ( token:: Bracket )
3619
- && ( before_slice || !after. is_empty ( ) ) {
3620
- break
3621
- }
3622
- }
3623
-
3624
- if before_slice {
3625
- if self . eat ( & token:: DotDot ) {
3626
-
3627
- if self . check ( & token:: Comma ) ||
3628
- self . check ( & token:: CloseDelim ( token:: Bracket ) ) {
3629
- slice = Some ( P ( Pat {
3630
- id : ast:: DUMMY_NODE_ID ,
3631
- node : PatKind :: Wild ,
3632
- span : self . prev_span ,
3633
- } ) ) ;
3634
- before_slice = false ;
3635
- }
3636
- continue
3637
- }
3638
- }
3639
-
3640
- let subpat = self . parse_pat ( None ) ?;
3641
- if before_slice && self . eat ( & token:: DotDot ) {
3642
- slice = Some ( subpat) ;
3643
- before_slice = false ;
3644
- } else if before_slice {
3645
- before. push ( subpat) ;
3646
- } else {
3647
- after. push ( subpat) ;
3648
- }
3649
- }
3650
-
3651
- Ok ( ( before, slice, after) )
3652
- }
3653
-
3654
3538
fn parse_pat_field (
3655
3539
& mut self ,
3656
3540
lo : Span ,
@@ -3862,6 +3746,17 @@ impl<'a> Parser<'a> {
3862
3746
} ) )
3863
3747
}
3864
3748
3749
+ /// Parse a parentesized comma separated sequence of patterns until `delim` is reached.
3750
+ fn parse_recover_pat_list ( & mut self ) -> PResult < ' a , ( ) > {
3751
+ while !self . check ( & token:: CloseDelim ( token:: Paren ) ) {
3752
+ self . parse_pat ( None ) ?;
3753
+ if !self . eat ( & token:: Comma ) {
3754
+ return Ok ( ( ) )
3755
+ }
3756
+ }
3757
+ Ok ( ( ) )
3758
+ }
3759
+
3865
3760
/// A wrapper around `parse_pat` with some special error handling for the
3866
3761
/// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast
3867
3762
/// to subpatterns within such).
@@ -3875,7 +3770,7 @@ impl<'a> Parser<'a> {
3875
3770
// later.
3876
3771
let comma_span = self . token . span ;
3877
3772
self . bump ( ) ;
3878
- if let Err ( mut err) = self . parse_pat_list ( ) {
3773
+ if let Err ( mut err) = self . parse_recover_pat_list ( ) {
3879
3774
// We didn't expect this to work anyway; we just wanted
3880
3775
// to advance to the end of the comma-sequence so we know
3881
3776
// the span to suggest parenthesizing
@@ -3933,20 +3828,24 @@ impl<'a> Parser<'a> {
3933
3828
pat = PatKind :: Ref ( subpat, mutbl) ;
3934
3829
}
3935
3830
token:: OpenDelim ( token:: Paren ) => {
3936
- // Parse (pat,pat,pat,...) as tuple pattern
3937
- let ( fields, ddpos, trailing_comma) = self . parse_parenthesized_pat_list ( ) ?;
3938
- pat = if fields. len ( ) == 1 && ddpos. is_none ( ) && !trailing_comma {
3831
+ // Parse `(pat, pat, pat, ...)` as tuple pattern.
3832
+ let ( fields, trailing_comma) = self . parse_paren_comma_seq ( |p| p. parse_pat ( None ) ) ?;
3833
+
3834
+ pat = if fields. len ( ) == 1 && !( trailing_comma || fields[ 0 ] . is_rest ( ) ) {
3939
3835
PatKind :: Paren ( fields. into_iter ( ) . nth ( 0 ) . unwrap ( ) )
3940
3836
} else {
3941
- PatKind :: Tuple ( fields, ddpos )
3837
+ PatKind :: Tuple ( fields)
3942
3838
} ;
3943
3839
}
3944
3840
token:: OpenDelim ( token:: Bracket ) => {
3945
- // Parse [pat,pat,...] as slice pattern
3841
+ // Parse `[pat, pat,...]` as a slice pattern.
3842
+ let ( slice, _) = self . parse_delim_comma_seq ( token:: Bracket , |p| p. parse_pat ( None ) ) ?;
3843
+ pat = PatKind :: Slice ( slice) ;
3844
+ }
3845
+ token:: DotDot => {
3846
+ // Parse `..`.
3946
3847
self . bump ( ) ;
3947
- let ( before, slice, after) = self . parse_pat_vec_elements ( ) ?;
3948
- self . expect ( & token:: CloseDelim ( token:: Bracket ) ) ?;
3949
- pat = PatKind :: Slice ( before, slice, after) ;
3848
+ pat = PatKind :: Rest ;
3950
3849
}
3951
3850
// At this point, token != &, &&, (, [
3952
3851
_ => if self . eat_keyword ( kw:: Underscore ) {
@@ -4044,8 +3943,8 @@ impl<'a> Parser<'a> {
4044
3943
return Err ( err) ;
4045
3944
}
4046
3945
// Parse tuple struct or enum pattern
4047
- let ( fields, ddpos , _) = self . parse_parenthesized_pat_list ( ) ?;
4048
- pat = PatKind :: TupleStruct ( path, fields, ddpos )
3946
+ let ( fields, _) = self . parse_paren_comma_seq ( |p| p . parse_pat ( None ) ) ?;
3947
+ pat = PatKind :: TupleStruct ( path, fields)
4049
3948
}
4050
3949
_ => pat = PatKind :: Path ( qself, path) ,
4051
3950
}
0 commit comments