@@ -41,33 +41,67 @@ Sub-slices and sub-arrays can be matched using `..` and `<IDENT> @ ..` can be us
4141these sub-slices and sub-arrays to an identifier.
4242
4343``` rust
44- // Matching slices using `ref` patterns:
45- let v = vec! [1 , 2 , 3 ];
44+ // Matching slices using `ref` and `ref mut` patterns:
45+ let mut v = vec! [1 , 2 , 3 ];
4646match v [.. ] {
47- [1 , ref subslice @ .. , 4 ] => assert_eq! (subslice . len (), 1 ),
48- [5 , ref subslice @ .. ] => assert_eq! (subslice . len (), 2 ),
49- [ref subslice @ .. , 6 ] => assert_eq! (subslice . len (), 2 ),
47+ [1 , ref subslice @ .. , 4 ] => assert_eq! (subslice . len (), 1 ), // typeof(subslice) == &[i32]
48+ [5 , ref subslice @ .. ] => assert_eq! (subslice . len (), 2 ), // typeof(subslice) == &[i32]
49+ [ref subslice @ .. , 6 ] => assert_eq! (subslice . len (), 2 ), // typeof(subslice) == &[i32]
50+ [x , .. , y ] => assert! (v . len () >= 2 ),
51+ [.. ] => {} // Always matches
52+ }
53+ match v [.. ] {
54+ [1 , ref mut subslice @ .. , 4 ] => assert_eq! (subslice . len (), 1 ), // typeof(subslice) == &mut [i32]
55+ [5 , ref mut subslice @ .. ] => assert_eq! (subslice . len (), 2 ), // typeof(subslice) == &mut [i32]
56+ [ref mut subslice @ .. , 6 ] => assert_eq! (subslice . len (), 2 ), // typeof(subslice) == &mut [i32]
5057 [x , .. , y ] => assert! (v . len () >= 2 ),
5158 [.. ] => {} // Always matches
5259}
5360
5461// Matching slices using default-binding-modes:
55- let v = vec! [1 , 2 , 3 ];
62+ let mut v = vec! [1 , 2 , 3 ];
5663match & v [.. ] {
57- [1 , subslice @ .. , 4 ] => assert_eq! (subslice . len (), 1 ),
58- [5 , subslice @ .. ] => assert_eq! (subslice . len (), 2 ),
59- [subslice @ .. , 6 ] => assert_eq! (subslice . len (), 2 ),
64+ [1 , subslice @ .. , 4 ] => assert_eq! (subslice . len (), 1 ), // typeof(subslice) == &[i32]
65+ [5 , subslice @ .. ] => assert_eq! (subslice . len (), 2 ), // typeof(subslice) == &[i32]
66+ [subslice @ .. , 6 ] => assert_eq! (subslice . len (), 2 ), // typeof(subslice) == &[i32]
67+ [x , .. , y ] => assert! (v . len () >= 2 ),
68+ [.. ] => {} // Always matches
69+ }
70+ match & mut v [.. ] {
71+ [1 , subslice @ .. , 4 ] => assert_eq! (subslice . len (), 1 ), // typeof(subslice) == &mut [i32]
72+ [5 , subslice @ .. ] => assert_eq! (subslice . len (), 2 ), // typeof(subslice) == &mut [i32]
73+ [subslice @ .. , 6 ] => assert_eq! (subslice . len (), 2 ), // typeof(subslice) == &mut [i32]
6074 [x , .. , y ] => assert! (v . len () >= 2 ),
6175 [.. ] => {} // Always matches
6276}
6377
64- // Matching arrays by-value:
65- let v = [1 , 2 , 3 ];
78+ // Matching slices by value (error):
79+ let mut v = vec! [1 , 2 , 3 ];
80+ match v [.. ] {
81+ [x @ .. ] => {} // ERROR cannot move out of type `[i32]`, a non-copy slice
82+ }
83+
84+ // Matching arrays by-value and by reference (explicitly or using default-binding-modes):
85+ let mut v = [1 , 2 , 3 ];
6686match v {
67- [1 , subarray @ .. , 3 ] => assert_eq! (subarray , [2 ]),
68- [5 , subarray @ .. ] => has_type :: <[i32 ; 2 ]>(subarray ),
69- [subarray @ .. , 6 ] => has_type :: <[i32 , 2 ]>(subarray ),
70- [x , .. , y ] => has_type :: <[i32 , 1 ]>(x ),
87+ [1 , subarray @ .. , 3 ] => assert_eq! (subarray , [2 ]), // typeof(subarray) == [i32; 1]
88+ [5 , subarray @ .. ] => has_type :: <[i32 ; 2 ]>(subarray ), // typeof(subarray) == [i32; 2]
89+ [subarray @ .. , 6 ] => has_type :: <[i32 , 2 ]>(subarray ), // typeof(subarray) == [i32; 2]
90+ [x , .. , y ] => has_type :: <[i32 , 1 ]>(x ), // typeof(subarray) == [i32; 1]
91+ [.. ] => {},
92+ }
93+ match v {
94+ [1 , ref subarray @ .. , 3 ] => assert_eq! (subarray , [2 ]), // typeof(subarray) == &[i32; 1]
95+ [5 , ref subarray @ .. ] => has_type :: <& [i32 ; 2 ]>(subarray ), // typeof(subarray) == &[i32; 2]
96+ [ref subarray @ .. , 6 ] => has_type :: <& [i32 , 2 ]>(subarray ), // typeof(subarray) == &[i32; 2]
97+ [x , .. , y ] => has_type :: <& [i32 , 1 ]>(x ), // typeof(subarray) == &[i32; 1]
98+ [.. ] => {},
99+ }
100+ match & mut v {
101+ [1 , subarray @ .. , 3 ] => assert_eq! (subarray , [2 ]), // typeof(subarray) == &mut [i32; 1]
102+ [5 , subarray @ .. ] => has_type :: <& mut [i32 ; 2 ]>(subarray ), // typeof(subarray) == &mut [i32; 2]
103+ [subarray @ .. , 6 ] => has_type :: <& mut [i32 , 2 ]>(subarray ), // typeof(subarray) == &mut [i32; 2]
104+ [x , .. , y ] => has_type :: <& mut [i32 , 1 ]>(x ), // typeof(subarray) == &mut [i32; 1]
71105 [.. ] => {},
72106}
73107```
@@ -82,9 +116,8 @@ reference or mutable reference to a slice or array.
82116
83117` @ ` can be used to bind the result of ` .. ` to an identifier.
84118
85- When used to match against a non-reference slice (` [u8] ` ), ` x @ .. ` would attempt to bind
86- by-value, which would fail in the case that users haven't enabled ` feature(unsized_locals) `
87- (since otherwise it's not possible to bind ` [u8] ` to a variable directly).
119+ When used to match against a non-reference slice (` [u8] ` ), ` x @ .. ` would attempt to bind
120+ by-value, which would fail due a move from a non-copy type ` [u8] ` .
88121
89122` .. ` /` IDENT @ .. ` is not a full pattern syntax, but rather a part of slice, tuple and tuple
90123struct pattern syntaxes. In particular, ` .. ` is not accepted by the ` pat ` macro matcher.
@@ -103,10 +136,10 @@ ambiguity with ranges, for example
103136[ ` .. @ PAT ` ] ( https://github.com/rust-lang/rust/issues/23121#issuecomment-280920062 ) or
104137[ ` PAT @ .. ` ] ( https://github.com/rust-lang/rust/issues/23121#issuecomment-280906823 ) , or other
105138similar alternatives.
106- We reject these syntaxes because they only bring benefits in incredibly contrived cases using a
139+ We reject these syntaxes because they only bring benefits in contrived cases using a
107140feature that doesn't even exist yet, but normally they only add symbolic noise.
108141
109- More radical syntax changes not keeping consistency with ` .. ` , for example
142+ More radical syntax changes do not keep consistency with ` .. ` , for example
110143[ ` [1, 2, 3, 4] ++ ref v ` ] ( https://github.com/rust-lang/rust/issues/23121#issuecomment-289220169 ) .
111144
112145### ` ..PAT ` or ` PAT.. `
@@ -118,30 +151,32 @@ The two simplest variations are `..PAT` and `PAT..`.
118151
119152#### Ambiguity
120153
121- The issue is that these syntaxes are ambiguous with half-bounded ranges ` ..END ` and ` BEGIN.. ` .
154+ The issue is that these syntaxes are ambiguous with half-bounded ranges ` ..END ` and ` BEGIN.. ` ,
155+ and the full range ` .. ` .
122156To be precise, such ranges are not currently supported in patterns, but they may be supported in
123157the future.
124158
125159Syntactic ambiguity is not inherently bad. We see it every day in expressions like
126160` a + b * c ` . What is important is to disambiguate it reasonably by default and have a way to
127161group operands in the alternative way when default disambiguation turns out to be incorrect.
128- In case of slice patterns the subslice interpretation seems overwhelmingly more likely, so we
162+ In case of slice patterns the subslice interpretation seems more likely, so we
129163can take it as a default.
130- There was no visible demand for implementing half-bounded ranges in patterns so far, but if they
164+ There was very little demand for implementing half-bounded ranges in patterns so far
165+ (see https://github.com/rust-lang/rfcs/issues/947 ), but if they
131166are implemented in the future they will be able to be used in slice patterns as well, but they
132- will require explicit grouping with recently implemented
167+ could require explicit grouping with recently implemented
133168[ parentheses in patterns] ( https://github.com/rust-lang/rust/pull/48500 ) (` [a, (..end)] ` ) or an
134169explicitly written start boundary (` [a, 0 .. end] ` ).
135170We can also make * some* disambiguation effort and, for example, interpret ` ..LITERAL ` as a
136171range because ` LITERAL ` can never match a subslice. Time will show if such an effort is necessary
137172or not.
138173
139- If/when half-bounded ranges are supported in patterns, for better future compatibility we'll need
140- to reserve ` ..PAT ` as "rest of the list" in tuples and tuple structs as well, and avoid interpreting
141- it as a range pattern in those positions.
174+ If/when half-bounded ranges are supported in patterns, for better future compatibility we could
175+ decide to reserve ` ..PAT ` as "rest of the list" in tuples and tuple structs as well, and avoid
176+ interpreting it as a range pattern in those positions.
142177
143178Note that ambiguity with unbounded ranges as they are used in expressions (` .. ` ) already exists in
144- variant ` Variant(..) ` and tuple ` (a, b, ..) ` patterns, but it's very unlikely that the ` .. ` syntax
179+ variant ` Variant(..) ` and tuple ` (a, b, ..) ` patterns, but it's unlikely that the ` .. ` syntax
145180will ever be used in patterns in the range meaning because it duplicates functionality of the
146181wildcard pattern ` _ ` .
147182
@@ -153,15 +188,15 @@ That RFC received almost no discussion before it got merged and its motivation i
153188relevant because arrays now use syntax ` [T; N] ` instead of ` [T, ..N] ` used in old Rust.
154189
155190This RFC originally proposed to switch back to ` ..PAT ` .
156- Some reasons to switch:
191+ Some reasons to switch were :
157192- Symmetry with expressions.
158193One of the general ideas behind patterns is that destructuring with
159194patterns has the same syntax as construction with expressions, if possible.
160195In expressions we already have something with the meaning "rest of the list" - functional record
161196update in struct expressions ` S { field1, field2, ..remaining_fields } ` .
162197Right now we can use ` S { field1, field1, .. } ` in a pattern, but can't bind the remaining fields
163198as a whole (by creating a new struct type on the fly, for example). It's not inconceivable that
164- in Rust 2525 we have such ability and it's reasonable to expect it using syntax ` ..remaining_fields `
199+ in Rust 2030 we have such ability and it's reasonable to expect it using syntax ` ..remaining_fields `
165200symmetric to expressions. It would be good for slice patterns to be consistent with it.
166201Without speculations, even if ` ..remaining_fields ` in struct expressions and ` ..subslice ` in slice
167202patterns are not entirely the same thing, they are similar enough to keep them symmetric already.
@@ -176,7 +211,7 @@ avoid if possible.
176211
177212This RFC no longer includes the addition of ` ..PAT ` or ` PAT.. ` , but merely ` .. ` as it results in
178213a smaller starting surface-area for the feature which can be expanded in the future if necessary.
179- The currently-proposed change is an extremely minimal addition to patterns (` .. ` for slices) which
214+ The currently-proposed change is a minimal addition to patterns (` .. ` for slices) which
180215already exists in other forms (e.g. tuples) and generalizes well to pattern-matching out sub-tuples,
181216e.g. ` let (a, b @ .., c) = (1, 2, 3, 4); ` .
182217
0 commit comments