6
6
# Summary
7
7
[ summary ] : #summary
8
8
9
- Tuple ` struct ` s can now be constructed with ` Self(v1, v2, ..) `
10
- to match how ` struct ` s with named fields can be constructed
11
- using ` Self { f1: v1, f2: v2, .. } ` . A simple example:
9
+ Tuple ` struct ` s can now be constructed and pattern matched with
10
+ ` Self(v1, v2, ..) ` . A simple example:
12
11
13
12
``` rust
14
13
struct TheAnswer (usize );
@@ -18,6 +17,8 @@ impl Default for TheAnswer {
18
17
}
19
18
```
20
19
20
+ Similarly, unit structs can also be constructed and pattern matched with ` Self ` .
21
+
21
22
# Motivation
22
23
[ motivation ] : #motivation
23
24
@@ -67,8 +68,8 @@ keep the type name fresh in their working memory. This is beneficial for
67
68
users with shorter working memory such as the author of this RFC.
68
69
69
70
Since ` Self { f0: v0, .. } ` is well motivated, those benefits and motivations
70
- will also extend to tuple structs. Eliminating this discrepancy between tuple
71
- structs and those with named fields will therefore have all the benefits
71
+ will also extend to tuple and unit structs. Eliminating this discrepancy between
72
+ tuple structs and those with named fields will therefore have all the benefits
72
73
associated with this feature for structs with named fields.
73
74
74
75
# Guide-level explanation
@@ -129,6 +130,90 @@ impl Default for BarFoo {
129
130
}
130
131
```
131
132
133
+ ## Patterns
134
+
135
+ Currently, you can pattern match using ` Self { .. } ` on a named struct as in
136
+ the following example:
137
+
138
+ ``` rust
139
+ struct Person {
140
+ ssn : usize ,
141
+ age : usize
142
+ }
143
+
144
+ impl Person {
145
+ /// Make a newborn person.
146
+ fn newborn (ssn : usize ) -> Self {
147
+ match { Self { ssn , age : 0 } } {
148
+ Self { ssn , age } // `Self { .. }` is permitted as a pattern!
149
+ => Self { ssn , age }
150
+ }
151
+ }
152
+ }
153
+ ```
154
+
155
+ This RFC extends this to tuple structs:
156
+
157
+ ``` rust
158
+ struct Person (usize , usize );
159
+
160
+ impl Person {
161
+ /// Make a newborn person.
162
+ fn newborn (ssn : usize ) -> Self {
163
+ match { Self (ssn , 0 ) } {
164
+ Self (ssn , age ) // `Self(..)` is permitted as a pattern!
165
+ => Self (ssn , age )
166
+ }
167
+ }
168
+ }
169
+ ```
170
+
171
+ Of course, this redundant reconstruction is not recommended in actual code,
172
+ but illustrates what you can do.
173
+
174
+ ## ` Self ` as a function pointer
175
+
176
+ When you define a tuple struct today such as:
177
+
178
+ ``` rust
179
+ struct Foo <T >(T );
180
+
181
+ impl <T > Foo <T > {
182
+ fn fooify_iter (iter : impl Iterator <Item = T >) -> impl Iterator <Item = Foo <T >> {
183
+ iter . map (Foo )
184
+ }
185
+ }
186
+ ```
187
+
188
+ you can use ` Foo ` as a function pointer typed at: ` for<T> fn(T) -> T ` as
189
+ seen in the example above.
190
+
191
+ This RFC extends that such that ` Self ` can also be used as a function pointer
192
+ for tuple structs. Modifying the example above gives us:
193
+
194
+ ``` rust
195
+ impl <T > Foo <T > {
196
+ fn fooify_iter (iter : impl Iterator <Item = T >) -> impl Iterator <Item = Foo <T >> {
197
+ iter . map (Self )
198
+ }
199
+ }
200
+ ```
201
+
202
+ ## Unit structs
203
+
204
+ With this RFC, you can also use ` Self ` in pattern and expression contexts when
205
+ dealing with unit structs. For example:
206
+
207
+ ``` rust
208
+ struct TheAnswer ;
209
+
210
+ impl Default for TheAnswer {
211
+ fn default () -> Self {
212
+ match { Self } { Self => Self }
213
+ }
214
+ }
215
+ ```
216
+
132
217
## Teaching the contents
133
218
134
219
This RFC should not require additional effort other than spreading the
@@ -139,23 +224,97 @@ should work and will probably try at some point.
139
224
# Reference-level explanation
140
225
[ reference-level-explanation ] : #reference-level-explanation
141
226
142
- Rust (now) allows usage of ` Self(v0, v1, ..) ` inside inherent
143
- and trait ` impl ` s of tuple structs, either when mentioning the
144
- tuple struct directly in the ` impl ` header, or via a type alias.
227
+ ## Grammar
228
+
229
+ Given:
230
+
231
+ ```
232
+ %token SELF
233
+ ```
234
+
235
+ which lexes ` Self ` , the following are legal productions in the language:
236
+
237
+ ```
238
+ pat : ... // <-- The original grammar of `pat` prior to this RFC.
239
+ | SELF '(' ')'
240
+ | SELF '(' pat_tup ')'
241
+ | SELF
242
+ | ...
243
+ ;
244
+
245
+ expr : ... // <-- Original grammar of `expr`.
246
+ | SELF '(' maybe_exprs ')'
247
+ | ...
248
+ ;
249
+ ```
250
+
251
+ ## Semantics
252
+
253
+ When entering one of the following contexts, a Rust compiler will extend
254
+ the value namespace with ` Self ` which maps to the tuple constructor ` fn `
255
+ in the case of tuple struct, or a constant, in the case of a unit struct:
256
+
257
+ + inherent ` impl ` s where the ` Self ` type is a tuple or unit struct
258
+ + ` trait ` ` impl ` s where the ` Self ` type is a tuple or unit struct
145
259
146
- ## Desugaring
260
+ As a result, when referring to a tuple struct, ` Self ` can be legally coerced
261
+ into an ` fn ` pointer which accepts and returns expressions of the same type as
262
+ the function pointer ` Self ` is referring to accepts.
147
263
148
- When the compiler encounters the following syntactic form specified in ` EBNF ` :
264
+ Another consequence is that ` Self(p_0, .., p_n) ` and ` Self ` become
265
+ legal patterns. This works since ` TupleCtor(p_0, .., p_n) ` patterns are
266
+ handled by resolving them in the value namespace and checking that they
267
+ resolve to a tuple constructor. Since by definition, ` Self ` referring
268
+ to a tuple struct resolves to a tuple constructor, this is OK.
149
269
150
- ``` ebnf
151
- SelfTupleApply ::= "Self" "(" ExprList ")" ;
152
- ExprList ::= Expr "," Values | Expr | "" ;
270
+ ## Implementation notes
271
+
272
+ As an additional check on the sanity of a Rust compiler implementation,
273
+ a well formed expression ` Self(v0, v1, ..) ` , must be semantically equivalent to
274
+ ` Self { 0: v0, 1: v1, .. } ` and must also be permitted when the latter would.
275
+ Likewise the pattern ` Self(p0, p1, ..) ` must match exactly the same set of
276
+ values as ` Self { 0: p0, 1: p1, .. } ` would and must be permitted when
277
+ ` Self { 0: p0, 1: p1, .. } ` is well formed.
278
+
279
+ Furthermore, a well formed expression or pattern ` Self ` must be semantically
280
+ equivalent to ` Self {} ` and permitted when ` Self {} ` is well formed in the
281
+ same context.
282
+
283
+ For example for tuple structs, we have the typing rule:
284
+
285
+ ```
286
+ Δ ⊢ τ_0 type .. Δ ⊢ τ_n type
287
+ Δ ⊢ Self type
288
+ Γ ⊢ x_0 : τ_0 .. Γ ⊢ x_n : τ_n
289
+ Γ ⊢ Self { 0: x_0, .. n: x_n } : Self
290
+ -----------------------------------------
291
+ Γ ⊢ Self ( x_0, .., x_n ) : Self
153
292
```
154
293
155
- the compiler will desugar the application by substituting ` Self(v0, v1, ..) `
156
- for ` Self { 0: v0, 1: v1, .. } ` and then continue on from there. The compiler
157
- is however free to use more direct or other approaches as long as it preserves
158
- the semantics of desugaring to ` Self { 0: v0, 1: v1, .. } ` .
294
+ and the operational semantics:
295
+
296
+ ```
297
+ Γ ⊢ Self { 0: e_0, .., n: e_n } ⇓ v
298
+ -------------------------------------
299
+ Γ ⊢ Self { e_0, .., e_n } ⇓ v
300
+ ```
301
+
302
+ for unit structs, the following holds:
303
+
304
+ ```
305
+ Δ ⊢ Self type
306
+ Γ ⊢ Self {} : Self
307
+ -----------------------------------------
308
+ Γ ⊢ Self : Self
309
+ ```
310
+
311
+ with the operational semantics:
312
+
313
+ ```
314
+ Γ ⊢ Self {} ⇓ v
315
+ -------------------------------------
316
+ Γ ⊢ Self ⇓ v
317
+ ```
159
318
160
319
## In relation to other RFCs
161
320
@@ -184,15 +343,4 @@ and unintuitive surprises for developers.
184
343
# Unresolved questions
185
344
[ unresolved ] : #unresolved-questions
186
345
187
- The following questions should be resolved during the RFC period:
188
-
189
- + Are there any syntactic ambiguities?
190
-
191
- To the author's knowledge, there are none since following fails to compile today:
192
-
193
- ``` rust
194
- fn Self (x : u8 ) {} // <-- an error here since Self is a keyword.
195
-
196
- struct F (u8 );
197
- impl F { fn x () { Self (0 ) } }
198
- ```
346
+ There are none.
0 commit comments