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