Skip to content

Commit c56927d

Browse files
committed
explain problems around references in constants
1 parent cb97a08 commit c56927d

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ which sort of is a virtual machine using `MIR` as "bytecode".
2121
## Table of Contents
2222

2323
* [Const Safety](const_safety.md)
24-
* [Promotion](const_safety.md)
24+
* [Constant References](const_refs.md)
25+
* [Promotion](promotion.md)
2526

2627
## Related RFCs
2728

const_refs.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# References in constants
2+
3+
Constants of reference type are not an entirely straight-forward topic, for
4+
reasonins unrelated to [const safety](const_safety.md). The issue is that
5+
every use of a constant like
6+
```rust
7+
const REF: &u32 = &42;
8+
```
9+
is supposed to behave as if the value of the constant was copy-pasted into every
10+
place where it is used. However, the *real* behavior is that a single global
11+
"static" allocation is created containing the `42`, and every use of `REF` gets
12+
evaluated to the address of that static. There are three reasons why this could
13+
be an issue.
14+
15+
## Pointer equality
16+
17+
We effectively "deduplicate" all the `42` that would otherwise locally be
18+
created at each use site of `REF`. This is observable when the programs
19+
compares these pointers for equality. We consider this okay, i.e., programs may
20+
not rely on such constants all getting distinct addresses. They may not rely on
21+
them all getting the same address either.
22+
23+
## Interior mutability
24+
25+
If the reference has type `&Cell<i32>` it is quite clear that the program can
26+
easily observe whether two references point to the same memory even without
27+
comparing their address: Changes through one reference will affect reads through
28+
the other. So, we cannot allow constant references to types that have interior
29+
mutability (types that are not `Freeze`).
30+
31+
However, we can do better than that: Even if a *type* is not `Freeze`, it can
32+
have *values* that do not exhibit any interior mutability. For example, `&None`
33+
at type `&Option<Cell<i32>>` would be rejected by the naive analysis above, but
34+
is actually accepted by the compiler because we know that there is no
35+
`UnsafeCell` here that would permit interior mutability.
36+
37+
## `Sync`
38+
39+
Finally, the same constant reference is actually shared across threads. This is
40+
very similar to multiple threads having a shared reference to the same `static`,
41+
which is why `static` must be `Sync`. So it seems like we should reject
42+
non-`Sync` types.
43+
44+
However, this does not currently happen, and there are several crates across the
45+
ecosystem that would break if we just started enforcing this now. See
46+
[this issue](https://github.com/rust-lang/rust/issues/49206) and the
47+
[PR attempting to fix this](https://github.com/rust-lang/rust/pull/54424/).

promotion.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ way when working with const-safe arguments.
8686

8787
TODO: Fill this with information.
8888

89-
### 4. Interior Mutability
89+
### 4. Reference constraints
9090

91-
TODO: Fill this with information.
91+
[Constant references](const_refs.md) impose some restrictions on the data they
92+
point to; the same restrictions apply to promoteds.
9293

9394
## Open questions
9495

0 commit comments

Comments
 (0)