Skip to content

Commit 9a23ee2

Browse files
committed
Merge remote-tracking branch 'petrochenkov/adtkinds'
2 parents 467ae3c + 433edd9 commit 9a23ee2

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

text/0000-adt-kinds.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
- Feature Name: clarified_adt_kinds
2+
- Start Date: 2016-02-07
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Provide a simple model describing three kinds of structs and variants and their relationships.
10+
Provide a way to match on structs/variants in patterns regardless of their kind (`S{..}`).
11+
Permit tuple structs and tuple variants with zero fields (`TS()`).
12+
13+
# Motivation
14+
[motivation]: #motivation
15+
16+
There's some mental model lying under the current implementation of ADTs, but it is not written
17+
out explicitly and not implemented completely consistently.
18+
Writing this model out helps to identify its missing parts.
19+
Some of this missing parts turn out to be practically useful.
20+
This RFC can also serve as a piece of documentation.
21+
22+
# Detailed design
23+
[design]: #detailed-design
24+
25+
The text below mostly talks about structures, but almost everything is equally applicable to
26+
variants.
27+
28+
## Braced structs
29+
30+
Braced structs are declared with braces (unsurprisingly).
31+
32+
```
33+
struct S {
34+
field1: Type1,
35+
field2: Type2,
36+
field3: Type3,
37+
}
38+
```
39+
40+
Braced structs are the basic struct kind, other kinds are built on top of them.
41+
Braced structs have 0 or more user-named fields and are defined only in type namespace.
42+
43+
Braced structs can be used in struct expressions `S{field1: expr, field2: expr}`, including
44+
functional record update (FRU) `S{field1: expr, ..s}`/`S{..s}` and with struct patterns
45+
`S{field1: pat, field2: pat}`/`S{field1: pat, ..}`/`S{..}`.
46+
In all cases the path `S` of the expression or pattern is looked up in the type namespace (so these
47+
expressions/patterns can be used with type aliases).
48+
Fields of a braced struct can be accessed with dot syntax `s.field1`.
49+
50+
Note: struct *variants* are currently defined in the value namespace in addition to type namespace,
51+
there are no particular reasons for this and this is probably temporary.
52+
53+
## Unit structs
54+
55+
Unit structs are defined without any fields or brackets.
56+
57+
```
58+
struct US;
59+
```
60+
61+
Unit structs can be thought of as a single declaration for two things: a basic struct
62+
63+
```
64+
struct US {}
65+
```
66+
67+
and a constant with the same name<sup>Note 1</sup>
68+
69+
```
70+
const US: US = US{};
71+
```
72+
73+
Unit structs have 0 fields and are defined in both type (the type `US`) and value (the
74+
constant `US`) namespaces.
75+
76+
As a basic struct, a unit struct can participate in struct expressions `US{}`, including FRU
77+
`US{..s}` and in struct patterns `US{}`/`US{..}`. In both cases the path `US` of the expression
78+
or pattern is looked up in the type namespace (so these expressions/patterns can be used with type
79+
aliases).
80+
Fields of a unit struct could also be accessed with dot syntax, but it doesn't have any fields.
81+
82+
As a constant, a unit struct can participate in unit struct expressions `US` and unit struct
83+
patterns `US`, both of these are looked up in the value namespace in which the constant `US` is
84+
defined (so these expressions/patterns cannot be used with type aliases).
85+
86+
Note 1: the constant is not exactly a `const` item, there are subtle differences (e.g. with regards
87+
to `match` exhaustiveness), but it's a close approximation.
88+
Note 2: the constant is pretty weirdly namespaced in case of unit *variants*, constants can't be
89+
defined in "enum modules" manually.
90+
91+
## Tuple structs
92+
93+
Tuple structs are declared with parentheses.
94+
```
95+
struct TS(Type0, Type1, Type2);
96+
```
97+
98+
Tuple structs can be thought of as a single declaration for two things: a basic struct
99+
100+
```
101+
struct TS {
102+
0: Type0,
103+
1: Type1,
104+
2: Type2,
105+
}
106+
```
107+
108+
and a constructor function with the same name<sup>Note 2</sup>
109+
110+
```
111+
fn TS(arg0: Type0, arg1: Type1, arg2: Type2) -> TS {
112+
TS{0: arg0, 1: arg1, 2: arg2}
113+
}
114+
```
115+
116+
Tuple structs have 0 or more automatically-named fields and are defined in both type (the type `TS`)
117+
and the value (the constructor function `TS`) namespaces.
118+
119+
As a basic struct, a tuple struct can participate in struct expressions `TS{0: expr, 1: expr}`,
120+
including FRU `TS{0: expr, ..ts}`/`TS{..ts}` and in struct patterns
121+
`TS{0: pat, 1: pat}`/`TS{0: pat, ..}`/`TS{..}`.
122+
In both cases the path `TS` of the expression or pattern is looked up in the type namespace (so
123+
these expressions/patterns can be used with type aliases).
124+
Fields of a tuple struct can be accessed with dot syntax `ts.0`.
125+
126+
As a constructor, a tuple struct can participate in tuple struct expressions `TS(expr, expr)` and
127+
tuple struct patterns `TS(pat, pat)`/`TS(..)`, both of these are looked up in the value namespace
128+
in which the constructor `TS` is defined (so these expressions/patterns cannot be used with type
129+
aliases). Tuple struct expressions `TS(expr, expr)` are usual
130+
function calls, but the compiler reserves the right to make observable improvements to them based
131+
on the additional knowledge, that `TS` is a constructor.
132+
133+
Note 1: the automatically assigned field names are quite interesting, they are not identifiers
134+
lexically (they are integer literals), so such fields can't be defined manually.
135+
Note 2: the constructor function is not exactly a `fn` item, there are subtle differences (e.g. with
136+
regards to privacy checks), but it's a close approximation.
137+
138+
## Summary of the changes.
139+
140+
Everything related to braced structs and unit structs is already implemented.
141+
142+
New: Permit tuple structs and tuple variants with 0 fields. This restriction is artificial and can
143+
be lifted trivially. Macro writers dealing with tuple structs/variants will be happy to get rid of
144+
this one special case.
145+
146+
New: Permit using tuple structs and tuple variants in braced struct patterns and expressions not
147+
requiring naming their fields - `TS{..ts}`/`TS{}`/`TS{..}`. This doesn't require much effort to
148+
implement as well.
149+
This also means that `S{..}` patterns can be used to match structures and variants of any kind.
150+
The desire to have such "match everything" patterns is sometimes expressed given
151+
that number of fields in structures and variants can change from zero to non-zero and back during
152+
development.
153+
An extra benefit is ability to match/construct tuple structs using their type aliases.
154+
155+
New: Permit using tuple structs and tuple variants in braced struct patterns and expressions
156+
requiring naming their fields - `TS{0: expr}`/`TS{0: pat}`/etc.
157+
While this change is important for consistency, there's not much motivation for it in hand-written
158+
code besides shortening patterns like `ItemFn(_, _, unsafety, _, _, _)` into something like
159+
`ItemFn{2: unsafety, ..}` and ability to match/construct tuple structs using their type aliases.
160+
However, automatic code generators (e.g. syntax extensions) can get more benefits from the
161+
ability to generate uniform code for all structure kinds.
162+
`#[derive]` for example, currently has separate code paths for generating expressions and patterns
163+
for braces structs (`ExprStruct`/`PatKind::Struct`), tuple structs
164+
(`ExprCall`/`PatKind::TupleStruct`) and unit structs (`ExprPath`/`PatKind::Path`). With proposed
165+
changes `#[derive]` could simplify its logic and always generate braced forms for expressions and
166+
patterns.
167+
168+
# Drawbacks
169+
[drawbacks]: #drawbacks
170+
171+
None.
172+
173+
# Alternatives
174+
[alternatives]: #alternatives
175+
176+
None.
177+
178+
# Unresolved questions
179+
[unresolved]: #unresolved-questions
180+
181+
None.

0 commit comments

Comments
 (0)