Skip to content

Commit fe85d88

Browse files
committed
Remove StructExprTuple and StructExprUnit
This removes the grammar rules StructExprTuple and StructExprUnit, and removes these as distinct expressions. Instead, a note block is used to let the reader know how the constructors can be accessed in the value namespace. This stems back to the beginning of this documentation, which presumably was presenting these as distinct kinds of expressions just as a simplification or to match what people's mental models might be. However, they are not distinct expressions, and I think it is misleading to pretend that they are. Closes rust-lang#1802
1 parent 48ad733 commit fe85d88

File tree

5 files changed

+52
-86
lines changed

5 files changed

+52
-86
lines changed

src/expressions.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,8 @@ They are never allowed before:
347347
[Structs]: expr.struct
348348
[Temporary values]: #temporaries
349349
[tuple expressions]: expressions/tuple-expr.md
350-
[Tuple structs]: expr.struct.tuple
350+
[Tuple structs]: items.struct.tuple
351351
[Tuples]: expressions/tuple-expr.md
352352
[Underscores]: expressions/underscore-expr.md
353-
[Unit structs]: expr.struct.unit
353+
[Unit structs]: items.struct.unit
354354
[Variables]: variables.md

src/expressions/if-expr.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ r[expr.if]
66
r[expr.if.syntax]
77
```grammar,expressions
88
IfExpression ->
9-
`if` Expression _except [StructExprStruct]_ BlockExpression
9+
`if` Expression _except [StructExpression]_ BlockExpression
1010
(`else` ( BlockExpression | IfExpression | IfLetExpression ) )?
1111
```
1212
<!-- TODO: The exception above isn't accurate, see https://github.com/rust-lang/reference/issues/569 -->

src/expressions/loop-expr.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ r[expr.loop.while]
5454

5555
r[expr.loop.while.syntax]
5656
```grammar,expressions
57-
PredicateLoopExpression -> `while` Expression _except [StructExprStruct]_ BlockExpression
57+
PredicateLoopExpression -> `while` Expression _except [StructExpression]_ BlockExpression
5858
```
5959
<!-- TODO: The exception above isn't accurate, see https://github.com/rust-lang/reference/issues/569 -->
6060

@@ -148,7 +148,7 @@ r[expr.loop.for]
148148
r[expr.loop.for.syntax]
149149
```grammar,expressions
150150
IteratorLoopExpression ->
151-
`for` Pattern `in` Expression _except [StructExprStruct]_ BlockExpression
151+
`for` Pattern `in` Expression _except [StructExpression]_ BlockExpression
152152
```
153153
<!-- TODO: The exception above isn't accurate, see https://github.com/rust-lang/reference/issues/569 -->
154154

src/expressions/match-expr.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ MatchExpression ->
99
MatchArms?
1010
`}`
1111
12-
Scrutinee -> Expression _except [StructExprStruct]_
12+
Scrutinee -> Expression _except [StructExpression]_
1313
1414
MatchArms ->
1515
( MatchArm `=>` ( ExpressionWithoutBlock `,` | ExpressionWithBlock `,`? ) )*

src/expressions/struct-expr.md

+46-80
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@ r[expr.struct]
44
r[expr.struct.syntax]
55
```grammar,expressions
66
StructExpression ->
7-
StructExprStruct
8-
| StructExprTuple
9-
| StructExprUnit
10-
11-
StructExprStruct ->
127
PathInExpression `{` (StructExprFields | StructBase)? `}`
138
149
StructExprFields ->
@@ -22,35 +17,70 @@ StructExprField ->
2217
)
2318
2419
StructBase -> `..` Expression
25-
26-
StructExprTuple -> CallExpression
27-
28-
StructExprUnit -> PathExpression
2920
```
3021

3122
r[expr.struct.intro]
3223
A *struct expression* creates a struct, enum, or union value.
3324
It consists of a path to a [struct], [enum variant], or [union] item followed by the values for the fields of the item.
34-
There are three forms of struct expressions: struct, tuple, and unit.
3525

3626
The following are examples of struct expressions:
3727

3828
```rust
3929
# struct Point { x: f64, y: f64 }
4030
# struct NothingInMe { }
41-
# struct TuplePoint(f64, f64);
4231
# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } }
43-
# struct Cookie; fn some_fn<T>(t: T) {}
4432
# enum Enum { Variant {} }
4533
Point {x: 10.0, y: 20.0};
4634
NothingInMe {};
47-
TuplePoint(10.0, 20.0);
48-
TuplePoint { 0: 10.0, 1: 20.0 }; // Results in the same value as the above line
4935
let u = game::User {name: "Joe", age: 35, score: 100_000};
5036
Enum::Variant {};
51-
some_fn::<Cookie>(Cookie);
5237
```
5338

39+
> [!NOTE]
40+
> Tuple structs and tuple enum variants are typically instantiated using a [call expression][expr.call] referring to the [constructor in the value namespace][items.struct.tuple]. These are distinct from a struct expression using curly braces referring to the constructor in the type namespace.
41+
>
42+
> ```rust
43+
> struct Position(i32, i32, i32);
44+
> Position(0, 0, 0); // Typical way of creating a tuple struct.
45+
> let c = Position; // `c` is a function that takes 3 arguments.
46+
> let pos = c(8, 6, 7); // Creates a `Position` value.
47+
>
48+
> enum Version { Triple(i32, i32, i32) };
49+
> Version::Triple(0, 0, 0);
50+
> let f = Version::Triple;
51+
> let ver = f(8, 6, 7);
52+
> ```
53+
>
54+
> The last segment of the call path cannot refer to a type alias:
55+
>
56+
> ```rust
57+
> trait Tr { type T; }
58+
> impl<T> Tr for T { type T = T; }
59+
>
60+
> struct Tuple();
61+
> enum Enum { Tuple() }
62+
>
63+
> // <Unit as Tr>::T(); // causes an error -- `::T` is a type, not a value
64+
> <Enum as Tr>::T::Tuple(); // OK
65+
> ```
66+
>
67+
> ----
68+
>
69+
> Unit structs and unit enum variants are typically instantiated using a [path expression][expr.path] referring to the [constant in the value namespace][items.struct.unit].
70+
>
71+
> ```rust
72+
> struct Gamma;
73+
> // Gamma unit value, referring to the const in the value namespace.
74+
> let a = Gamma;
75+
> // Exact same value as `a`, but constructed using a struct expression
76+
> // referring to the type namespace.
77+
> let b = Gamma {};
78+
>
79+
> enum ColorSpace { Oklch }
80+
> let c = ColorSpace::Oklch;
81+
> let d = ColorSpace::Oklch {};
82+
> ```
83+
5484
r[expr.struct.field]
5585
## Field struct expression
5686
@@ -85,7 +115,7 @@ drop(y_ref);
85115
```
86116
87117
r[expr.struct.brace-restricted-positions]
88-
Struct expressions with curly braces can't be used directly in a [loop] or [if] expression's head, or in the [scrutinee] of an [if let] or [match] expression.
118+
Struct expressions can't be used directly in a [loop] or [if] expression's head, or in the [scrutinee] of an [if let] or [match] expression.
89119
However, struct expressions can be used in these situations if they are within another expression, for example inside [parentheses].
90120

91121
r[expr.struct.tuple-field]
@@ -115,70 +145,6 @@ Point3d { x: x, y: y_value, z: z };
115145
Point3d { x, y: y_value, z };
116146
```
117147

118-
r[expr.struct.tuple]
119-
## Tuple struct expression
120-
121-
A struct expression with fields enclosed in parentheses constructs a tuple struct or a tuple variant of an enum.
122-
Though it is listed here as a specific expression for completeness, it is equivalent to a [call expression] to the tuple struct's (enum tuple variant's) constructor. For example:
123-
124-
```rust
125-
struct Position(i32, i32, i32);
126-
Position(0, 0, 0); // Typical way of creating a tuple struct.
127-
let c = Position; // `c` is a function that takes 3 arguments.
128-
let pos = c(8, 6, 7); // Creates a `Position` value.
129-
130-
enum Version { Triple(i32, i32, i32) };
131-
Version::Triple(0, 0, 0);
132-
let f = Version::Triple;
133-
let ver = f(8, 6, 7);
134-
```
135-
136-
> [!NOTE]
137-
> While the grammar permits qualified paths, the last segment can't be a type alias:
138-
>
139-
> ```rust
140-
> trait Tr { type T; }
141-
> impl<T> Tr for T { type T = T; }
142-
>
143-
> struct Tuple();
144-
> enum Enum { Tuple() }
145-
>
146-
> // <Unit as Tr>::T(); // causes an error -- `::T` is a type, not a value
147-
> <Enum as Tr>::T::Tuple(); // OK
148-
> ```
149-
150-
r[expr.struct.unit]
151-
## Unit struct expression
152-
153-
A unit struct expression is just the path to a unit struct item or unit variant of an enum.
154-
This refers to the unit struct's (enum variant's) implicit constant of its value.
155-
The unit struct or a unit variant of an enum value can also be constructed with a fieldless struct expression. For example:
156-
157-
```rust
158-
struct Gamma;
159-
let a = Gamma; // Gamma unit value.
160-
let b = Gamma{}; // Exact same value as `a`.
161-
162-
enum ColorSpace { Oklch }
163-
let c = ColorSpace::Oklch;
164-
let d = ColorSpace::Oklch {};
165-
```
166-
167-
> [!NOTE]
168-
> While the grammar permits qualified paths, the last segment can't be a type alias:
169-
>
170-
> ```rust
171-
> trait Tr { type T; }
172-
> impl<T> Tr for T { type T = T; }
173-
>
174-
> struct Unit;
175-
> enum Enum { Unit }
176-
>
177-
> // <Unit as Tr>::T; // causes an error -- `::T` is a type, not a value
178-
> <Enum as Tr>::T::Unit; // OK
179-
> ```
180-
181-
[call expression]: call-expr.md
182148
[enum variant]: ../items/enumerations.md
183149
[if let]: if-expr.md#if-let-expressions
184150
[if]: if-expr.md#if-expressions

0 commit comments

Comments
 (0)