Skip to content

Commit e215e59

Browse files
committed
Added section on rvalues/temporaries
1 parent 7f4a612 commit e215e59

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

text/0000-type-ascription.md

+41
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,47 @@ work with only minor adjustment, it allows for a backwards compatible path to
149149
allows customisation of a contentious kind of error (especially so in the
150150
context of cross-platform programming).
151151

152+
153+
### Type ascription and temporaries
154+
155+
There is an implementation choice between treating `x: T` as an lvalue or
156+
rvalue. Note that when a rvalue is used in lvalue context (e.g., the subject of
157+
a reference operation), then the compiler introduces a temporary variable.
158+
Neither option is satisfactory, if we treat an ascription expression as an
159+
lvalue (i.e., no new temporary), then there is potential for unsoundness:
160+
161+
```
162+
let mut foo: S = ...;
163+
{
164+
let bar = &mut (foo: T); // S <: T, no coercion required
165+
*bar = ... : T;
166+
}
167+
// Whoops, foo has type T, but the compiler thinks it has type S, where potentially T </: S
168+
```
169+
170+
If we treat ascription expressions as rvalues (i.e., create a temporary in
171+
lvalue position), then we don't have the soundness problem, but we do get the
172+
unexpected result that `&(x: T)` is not in fact a reference to `x`, but a
173+
reference to a temporary copy of `x`.
174+
175+
The proposed solution is that type ascription expressions are rvalues, but
176+
taking a reference of such an expression is forbidden. I.e., type asciption is
177+
forbidden in the following contexts (where `<expr>` is a type ascription
178+
expression):
179+
180+
```
181+
&[mut] <expr>
182+
let ref [mut] x = <expr>
183+
match <expr> { .. ref [mut] x .. => { .. } .. }
184+
<expr>.foo() // due to autoref
185+
```
186+
187+
Like other rvalues, type ascription would not be allowed as the lhs of assignment.
188+
189+
Note that, if type asciption is required in such a context, an lvalue can be
190+
forced by using `{}`, e.g., write `&mut { foo: T }`, rather than `&mut (foo: T)`.
191+
192+
152193
# Drawbacks
153194

154195
More syntax, another feature in the language.

0 commit comments

Comments
 (0)