Skip to content

Commit 2a16873

Browse files
authored
Merge pull request #5 from Centril/patch-1/tuple-struct-self-ctor
Fix RFC 2302 to support unit structs, fn pointers, and use value namespace instead for exprs
2 parents e35521e + bcd03b2 commit 2a16873

File tree

1 file changed

+177
-29
lines changed

1 file changed

+177
-29
lines changed

text/0000-tuple-struct-self-ctor.md

Lines changed: 177 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
# Summary
77
[summary]: #summary
88

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:
1211

1312
```rust
1413
struct TheAnswer(usize);
@@ -18,6 +17,8 @@ impl Default for TheAnswer {
1817
}
1918
```
2019

20+
Similarly, unit structs can also be constructed and pattern matched with `Self`.
21+
2122
# Motivation
2223
[motivation]: #motivation
2324

@@ -67,8 +68,8 @@ keep the type name fresh in their working memory. This is beneficial for
6768
users with shorter working memory such as the author of this RFC.
6869

6970
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
7273
associated with this feature for structs with named fields.
7374

7475
# Guide-level explanation
@@ -129,6 +130,90 @@ impl Default for BarFoo {
129130
}
130131
```
131132

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+
132217
## Teaching the contents
133218

134219
This RFC should not require additional effort other than spreading the
@@ -139,23 +224,97 @@ should work and will probably try at some point.
139224
# Reference-level explanation
140225
[reference-level-explanation]: #reference-level-explanation
141226

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
145259

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.
147263

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.
149269

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
153292
```
154293

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+
```
159318

160319
## In relation to other RFCs
161320

@@ -184,15 +343,4 @@ and unintuitive surprises for developers.
184343
# Unresolved questions
185344
[unresolved]: #unresolved-questions
186345

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

Comments
 (0)