Skip to content

Commit 8928d68

Browse files
authored
Merge pull request #1 from Centril/patch-const-repeat-1
rfc, const-repeat-expr: notes on is_rvalue_promotable(expr)
2 parents 0b057bb + 38d278e commit 8928d68

File tree

1 file changed

+51
-26
lines changed

1 file changed

+51
-26
lines changed

text/0000-const-repeat-expr.md

+51-26
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
[summary]: #summary
88

99
Relaxes the rules for repeat expressions, `[x; N]` such that `x` may also be
10-
`const`, in addition to `typeof(x): Copy`. The result of `[x; N]` where `x` is
11-
`const` is itself also `const`.
10+
`const` *(strictly speaking rvalue promotable)*, in addition to `typeof(x): Copy`.
11+
The result of `[x; N]` where `x` is `const` is itself also `const`.
1212

1313
# Motivation
1414
[motivation]: #motivation
@@ -107,34 +107,51 @@ fn main() {
107107
internally as:
108108

109109
```rust
110-
// This is the value to be repeated and typeof(X) the type it has.
111-
// If a `VALUE` panics, it happens during compile time at this point
112-
// and not later.
113-
const X: typeof(X) = VALUE;
114-
115-
// N is the size of the array and how many times to repeat X.
116-
const N: usize = SIZE;
117-
118-
{
119-
let mut data: [typeof(X); N];
120-
121-
unsafe {
122-
data = mem::uninitialized();
123-
124-
let mut iter = (&mut data[..]).into_iter();
125-
while let Some(elem) = iter.next() {
126-
// ptr::write does not run destructor of elem already in array.
127-
// Since X is const, it can not panic at this point.
128-
ptr::write(elem, X);
110+
fn main() {
111+
type T = Option<Box<u32>>;
112+
113+
// This is the value to be repeated.
114+
// In this case, a panic won't happen, but if it did, that panic
115+
// would happen during compile time at this point and not later.
116+
const X: T = None;
117+
118+
let mut arr = {
119+
let mut data: [T; 2];
120+
121+
unsafe {
122+
data = mem::uninitialized();
123+
124+
let mut iter = (&mut data[..]).into_iter();
125+
while let Some(elem) = iter.next() {
126+
// ptr::write does not run destructor of elem already in array.
127+
// Since X is const, it can not panic at this point.
128+
ptr::write(elem, X);
129+
}
129130
}
130-
}
131131

132-
data
132+
data
133+
};
134+
135+
arr[0] = Some(Box::new(1));
133136
}
134137
```
135138

136-
Additionally, the pass that checks `const`ness must treat `[X; N]` as a `const`
137-
value.
139+
Additionally, the pass that checks `const`ness must treat `[expr; N]` as a
140+
`const` value such that `[expr; N]` is assignable to a `const` item as well
141+
as permitted inside a `const fn`.
142+
143+
Strictly speaking, the set of values permitted in the expression `[expr; N]`
144+
are those where `is_rvalue_promotable(expr)` or `typeof(expr): Copy`.
145+
Specifically, in `[expr; N]` the expression `expr` is evaluated:
146+
+ never, if `N == 0`,
147+
+ one time, if `N == 1`,
148+
+ `N` times, otherwise.
149+
150+
For values that are not freely duplicatable, evaluating `expr` will result in
151+
a move, which results in an error if `expr` is moved more than once (including
152+
moves outside of the repeat expression). These semantics are intentionally
153+
conservative and intended to be forward-compatible with a more expansive
154+
`is_const(expr)` check.
138155

139156
# Drawbacks
140157
[drawbacks]: #drawbacks
@@ -153,8 +170,16 @@ other constructs such as [`mem::uninitialized()`], for loops over iterators,
153170
this RFC is therefore the simplest and most non-intrusive design. It is also
154171
the most consistent.
155172

173+
Another alternative is to allow a more expansive set of values `is_const(expr)`
174+
rather than `is_rvalue_promotable(expr)`. A consequence of this is that checking
175+
constness would be done earlier on the HIR. Instead, checking if `expr` is
176+
rvalue promotable can be done on the MIR and does not require significant
177+
changes to the compiler. If we decide to expand to `is_const(expr)` in the
178+
future, we may still do so as the changes proposed in this RFC are
179+
compatible with such future changes.
180+
156181
The impact of not doing this change is to not enable generically sized arrays to
157-
be `const`.
182+
be `const` as well as encouraging the use of `mem::uninitialized`.
158183

159184
# Unresolved questions
160185
[unresolved]: #unresolved-questions

0 commit comments

Comments
 (0)