Skip to content

Commit 2bd29ae

Browse files
authored
Merge pull request #876 from ehuss/update-patterns-rest
Update patterns chapter, add rest patterns.
2 parents 281d576 + 589c216 commit 2bd29ae

File tree

1 file changed

+86
-10
lines changed

1 file changed

+86
-10
lines changed

src/patterns.md

+86-10
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22

33
> **<sup>Syntax</sup>**\
44
> _Pattern_ :\
5+
> &nbsp;&nbsp; &nbsp;&nbsp; _PatternWithoutRange_\
6+
> &nbsp;&nbsp; | [_RangePattern_]
7+
>
8+
> _PatternWithoutRange_ :\
59
> &nbsp;&nbsp; &nbsp;&nbsp; [_LiteralPattern_]\
610
> &nbsp;&nbsp; | [_IdentifierPattern_]\
711
> &nbsp;&nbsp; | [_WildcardPattern_]\
8-
> &nbsp;&nbsp; | [_RangePattern_]\
12+
> &nbsp;&nbsp; | [_RestPattern_]\
13+
> &nbsp;&nbsp; | [_ObsoleteRangePattern_]\
914
> &nbsp;&nbsp; | [_ReferencePattern_]\
1015
> &nbsp;&nbsp; | [_StructPattern_]\
1116
> &nbsp;&nbsp; | [_TupleStructPattern_]\
@@ -248,6 +253,9 @@ copying or moving what was matched.
248253
[Path patterns](#path-patterns) take precedence over identifier patterns. It is an error
249254
if `ref` or `ref mut` is specified and the identifier shadows a constant.
250255

256+
Identifier patterns are irrefutable if the `@` subpattern is irrefutable or
257+
the subpattern is not specified.
258+
251259
### Binding modes
252260

253261
To service better ergonomics, patterns operate in different *binding modes* in
@@ -317,12 +325,67 @@ if let Some(_) = x {}
317325

318326
The wildcard pattern is always irrefutable.
319327

328+
## Rest patterns
329+
330+
> **<sup>Syntax</sup>**\
331+
> _RestPattern_ :\
332+
> &nbsp;&nbsp; `..`
333+
334+
The _rest pattern_ (the `..` token) acts as a variable-length pattern which
335+
matches zero or more elements that haven't been matched already before and
336+
after. It may only be used in [tuple](#tuple-patterns), [tuple
337+
struct](#tuple-struct-patterns), and [slice](#slice-patterns) patterns, and
338+
may only appear once as one of the elements in those patterns. It is also
339+
allowed in an [identifier pattern](#identifier-patterns) for [slice
340+
patterns](#slice-patterns) only.
341+
342+
The rest pattern is always irrefutable.
343+
344+
Examples:
345+
346+
```rust
347+
# let words = vec!["a", "b", "c"];
348+
# let slice = &words[..];
349+
match slice {
350+
[] => println!("slice is empty"),
351+
[one] => println!("single element {}", one),
352+
[head, tail @ ..] => println!("head={} tail={:?}", head, tail),
353+
}
354+
355+
match slice {
356+
// Ignore everything but the last element, which must be "!".
357+
[.., "!"] => println!("!!!"),
358+
359+
// `start` is a slice of everything except the last element, which must be "z".
360+
[start @ .., "z"] => println!("starts with: {:?}", start),
361+
362+
// `end` is a slice of everything but the first element, which must be "a".
363+
["a", end @ ..] => println!("ends with: {:?}", end),
364+
365+
rest => println!("{:?}", rest),
366+
}
367+
368+
if let [.., penultimate, _] = slice {
369+
println!("next to last is {}", penultimate);
370+
}
371+
372+
# let tuple = (1, 2, 3, 4, 5);
373+
// Rest patterns may also be used in tuple and tuple struct patterns.
374+
match tuple {
375+
(1, .., y, z) => println!("y={} z={}", y, z),
376+
(.., 5) => println!("tail must be 5"),
377+
(..) => println!("matches everything else"),
378+
}
379+
```
380+
320381
## Range patterns
321382

322383
> **<sup>Syntax</sup>**\
323384
> _RangePattern_ :\
324-
> &nbsp;&nbsp;&nbsp;&nbsp; _RangePatternBound_ `..=` _RangePatternBound_\
325-
> &nbsp;&nbsp; | _RangePatternBound_ `...` _RangePatternBound_
385+
> &nbsp;&nbsp; _RangePatternBound_ `..=` _RangePatternBound_
386+
>
387+
> _ObsoleteRangePattern_ :\
388+
> &nbsp;&nbsp; _RangePatternBound_ `...` _RangePatternBound_
326389
>
327390
> _RangePatternBound_ :\
328391
> &nbsp;&nbsp; &nbsp;&nbsp; [CHAR_LITERAL]\
@@ -429,7 +492,7 @@ ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and
429492

430493
> **<sup>Syntax</sup>**\
431494
> _ReferencePattern_ :\
432-
> &nbsp;&nbsp; (`&`|`&&`) `mut`<sup>?</sup> _Pattern_
495+
> &nbsp;&nbsp; (`&`|`&&`) `mut`<sup>?</sup> [_PatternWithoutRange_]
433496
434497
Reference patterns dereference the pointers that are being matched
435498
and, thus, borrow them.
@@ -559,8 +622,7 @@ A struct pattern is refutable when one of its subpatterns is refutable.
559622
> &nbsp;&nbsp; [_PathInExpression_] `(` _TupleStructItems_<sup>?</sup> `)`
560623
>
561624
> _TupleStructItems_ :\
562-
> &nbsp;&nbsp; &nbsp;&nbsp; [_Pattern_]&nbsp;( `,` [_Pattern_] )<sup>\*</sup> `,`<sup>?</sup>\
563-
> &nbsp;&nbsp; | ([_Pattern_] `,`)<sup>\*</sup> `..` (`,` [_Pattern_])<sup>*</sup> `,`<sup>?</sup>
625+
> &nbsp;&nbsp; [_Pattern_]&nbsp;( `,` [_Pattern_] )<sup>\*</sup> `,`<sup>?</sup>
564626
565627
Tuple struct patterns match tuple struct and enum values that match all criteria defined
566628
by its subpatterns. They are also used to [destructure](#destructuring) a tuple struct or
@@ -576,13 +638,16 @@ A tuple struct pattern is refutable when one of its subpatterns is refutable.
576638
>
577639
> _TuplePatternItems_ :\
578640
> &nbsp;&nbsp; &nbsp;&nbsp; [_Pattern_] `,`\
579-
> &nbsp;&nbsp; | [_Pattern_]&nbsp;(`,` [_Pattern_])<sup>+</sup> `,`<sup>?</sup>\
580-
> &nbsp;&nbsp; | ([_Pattern_] `,`)<sup>\*</sup> `..` (`,` [_Pattern_])<sup>*</sup> `,`<sup>?</sup>
641+
> &nbsp;&nbsp; | [_RestPattern_]\
642+
> &nbsp;&nbsp; | [_Pattern_]&nbsp;(`,` [_Pattern_])<sup>+</sup> `,`<sup>?</sup>
581643
582644
Tuple patterns match tuple values that match all criteria defined by its subpatterns.
583645
They are also used to [destructure](#destructuring) a tuple.
584646

585-
This pattern is refutable when one of its subpatterns is refutable.
647+
The form `(..)` with a single [_RestPattern_] is a special form that does not
648+
require a comma, and matches a tuple of any size.
649+
650+
The tuple pattern is refutable when one of its subpatterns is refutable.
586651

587652
## Grouped patterns
588653

@@ -607,7 +672,10 @@ match int_reference {
607672

608673
> **<sup>Syntax</sup>**\
609674
> _SlicePattern_ :\
610-
> &nbsp;&nbsp; `[` [_Pattern_] \(`,` [_Pattern_])<sup>\*</sup> `,`<sup>?</sup> `]`
675+
> &nbsp;&nbsp; `[` _SlicePatternItems_<sup>?</sup> `]`
676+
>
677+
> _SlicePatternItems_ :\
678+
> &nbsp;&nbsp; [_Pattern_] \(`,` [_Pattern_])<sup>\*</sup> `,`<sup>?</sup>
611679
612680
Slice patterns can match both arrays of fixed size and slices of dynamic size.
613681
```rust
@@ -628,6 +696,11 @@ match v[..] {
628696
};
629697
```
630698

699+
Slice patterns are irrefutable when matching an array as long as each element
700+
is irrefutable. When matching a slice, it is irrefutable only in the form with
701+
a single `..` [rest pattern](#rest-patterns) or [identifier
702+
pattern](#identifier-patterns) with the `..` rest pattern as a subpattern.
703+
631704
## Path patterns
632705

633706
> **<sup>Syntax</sup>**\
@@ -658,12 +731,15 @@ refer to refutable constants or enum variants for enums with multiple variants.
658731
[_IdentifierPattern_]: #identifier-patterns
659732
[_LiteralPattern_]: #literal-patterns
660733
[_MacroInvocation_]: macros.md#macro-invocation
734+
[_ObsoleteRangePattern_]: #range-patterns
661735
[_PathInExpression_]: paths.md#paths-in-expressions
662736
[_PathPattern_]: #path-patterns
663737
[_Pattern_]: #patterns
738+
[_PatternWithoutRange_]: #patterns
664739
[_QualifiedPathInExpression_]: paths.md#qualified-paths
665740
[_RangePattern_]: #range-patterns
666741
[_ReferencePattern_]: #reference-patterns
742+
[_RestPattern_]: #rest-patterns
667743
[_SlicePattern_]: #slice-patterns
668744
[_StructPattern_]: #struct-patterns
669745
[_TuplePattern_]: #tuple-patterns

0 commit comments

Comments
 (0)