@@ -41,33 +41,67 @@ Sub-slices and sub-arrays can be matched using `..` and `<IDENT> @ ..` can be us
41
41
these sub-slices and sub-arrays to an identifier.
42
42
43
43
``` 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 ];
46
46
match 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]
50
57
[x , .. , y ] => assert! (v . len () >= 2 ),
51
58
[.. ] => {} // Always matches
52
59
}
53
60
54
61
// Matching slices using default-binding-modes:
55
- let v = vec! [1 , 2 , 3 ];
62
+ let mut v = vec! [1 , 2 , 3 ];
56
63
match & 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]
60
74
[x , .. , y ] => assert! (v . len () >= 2 ),
61
75
[.. ] => {} // Always matches
62
76
}
63
77
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 ];
66
86
match 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]
71
105
[.. ] => {},
72
106
}
73
107
```
@@ -82,9 +116,8 @@ reference or mutable reference to a slice or array.
82
116
83
117
` @ ` can be used to bind the result of ` .. ` to an identifier.
84
118
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] ` .
88
121
89
122
` .. ` /` IDENT @ .. ` is not a full pattern syntax, but rather a part of slice, tuple and tuple
90
123
struct pattern syntaxes. In particular, ` .. ` is not accepted by the ` pat ` macro matcher.
@@ -103,10 +136,10 @@ ambiguity with ranges, for example
103
136
[ ` .. @ PAT ` ] ( https://github.com/rust-lang/rust/issues/23121#issuecomment-280920062 ) or
104
137
[ ` PAT @ .. ` ] ( https://github.com/rust-lang/rust/issues/23121#issuecomment-280906823 ) , or other
105
138
similar 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
107
140
feature that doesn't even exist yet, but normally they only add symbolic noise.
108
141
109
- More radical syntax changes not keeping consistency with ` .. ` , for example
142
+ More radical syntax changes do not keep consistency with ` .. ` , for example
110
143
[ ` [1, 2, 3, 4] ++ ref v ` ] ( https://github.com/rust-lang/rust/issues/23121#issuecomment-289220169 ) .
111
144
112
145
### ` ..PAT ` or ` PAT.. `
@@ -118,30 +151,32 @@ The two simplest variations are `..PAT` and `PAT..`.
118
151
119
152
#### Ambiguity
120
153
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 ` .. ` .
122
156
To be precise, such ranges are not currently supported in patterns, but they may be supported in
123
157
the future.
124
158
125
159
Syntactic ambiguity is not inherently bad. We see it every day in expressions like
126
160
` a + b * c ` . What is important is to disambiguate it reasonably by default and have a way to
127
161
group 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
129
163
can 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
131
166
are 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
133
168
[ parentheses in patterns] ( https://github.com/rust-lang/rust/pull/48500 ) (` [a, (..end)] ` ) or an
134
169
explicitly written start boundary (` [a, 0 .. end] ` ).
135
170
We can also make * some* disambiguation effort and, for example, interpret ` ..LITERAL ` as a
136
171
range because ` LITERAL ` can never match a subslice. Time will show if such an effort is necessary
137
172
or not.
138
173
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.
142
177
143
178
Note 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
145
180
will ever be used in patterns in the range meaning because it duplicates functionality of the
146
181
wildcard pattern ` _ ` .
147
182
@@ -153,15 +188,15 @@ That RFC received almost no discussion before it got merged and its motivation i
153
188
relevant because arrays now use syntax ` [T; N] ` instead of ` [T, ..N] ` used in old Rust.
154
189
155
190
This RFC originally proposed to switch back to ` ..PAT ` .
156
- Some reasons to switch:
191
+ Some reasons to switch were :
157
192
- Symmetry with expressions.
158
193
One of the general ideas behind patterns is that destructuring with
159
194
patterns has the same syntax as construction with expressions, if possible.
160
195
In expressions we already have something with the meaning "rest of the list" - functional record
161
196
update in struct expressions ` S { field1, field2, ..remaining_fields } ` .
162
197
Right now we can use ` S { field1, field1, .. } ` in a pattern, but can't bind the remaining fields
163
198
as 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 `
165
200
symmetric to expressions. It would be good for slice patterns to be consistent with it.
166
201
Without speculations, even if ` ..remaining_fields ` in struct expressions and ` ..subslice ` in slice
167
202
patterns are not entirely the same thing, they are similar enough to keep them symmetric already.
@@ -176,7 +211,7 @@ avoid if possible.
176
211
177
212
This RFC no longer includes the addition of ` ..PAT ` or ` PAT.. ` , but merely ` .. ` as it results in
178
213
a 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
180
215
already exists in other forms (e.g. tuples) and generalizes well to pattern-matching out sub-tuples,
181
216
e.g. ` let (a, b @ .., c) = (1, 2, 3, 4); ` .
182
217
0 commit comments