You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rollup merge of #140942 - RalfJung:const-ref-to-mut, r=oli-obk
const-eval: allow constants to refer to mutable/external memory, but reject such constants as patterns
This fixes#140653 by accepting code such as this:
```rust
static FOO: AtomicU32 = AtomicU32::new(0);
const C: &'static AtomicU32 = &FOO;
```
This can be written entirely in safe code, so there can't really be anything wrong with it.
We also accept the much more questionable following code, since it looks very similar to the interpreter:
```rust
static mut FOO2: u32 = 0;
const C2: &'static u32 = unsafe { &mut FOO2 };
```
Using this without causing UB is at least very hard (the details are unclear since it is related to how the aliasing model deals with the staging of const-eval vs runtime code).
If a constant like `C2` is used as a pattern, we emit an error:
```
error: constant BAD_PATTERN cannot be used as pattern
--> $DIR/const_refs_to_static_fail.rs:30:9
|
LL | BAD_PATTERN => {},
| ^^^^^^^^^^^
|
= note: constants that reference mutable or external memory cannot be used as pattern
```
(If you somehow manage to build a pattern with constant `C`, you'd get the same error, but that should be impossible: we don't have a type that can be used in patterns and that has interior mutability.)
The same treatment is afforded for shared references to `extern static`, for the same reason: the const evaluation is entirely fine with it, we just can't build a pattern for it -- and when using interior mutability, this can be totally sound.
We do still not accept anything where there is an `&mut` in the final value of the const, as that should always require unsafe code and it's hard to imagine a sound use-case that would require this.
calling a function with argument of type {$callee_ty} passing data of type {$caller_ty}
126
126
127
-
const_eval_interior_mutable_ref_escaping =
128
-
{const_eval_const_context}s cannot refer to interior mutable data
129
-
.label = this borrow of an interior mutable value may end up in the final value
127
+
const_eval_interior_mutable_borrow_escaping =
128
+
interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a {const_eval_const_context} are not allowed
129
+
.label = this borrow of an interior mutable value refers to a lifetime-extended temporary
130
130
.help = to fix this, the value can be extracted to a separate `static` item and then referenced
131
131
.teach_note =
132
-
References that escape into the final value of a constant or static must be immutable.
132
+
This creates a raw pointer to a temporary that has its lifetime extended to last for the entire program.
133
+
Lifetime-extended temporaries in constants and statics must be immutable.
133
134
This is to avoid accidentally creating shared mutable state.
134
135
135
136
@@ -207,33 +208,23 @@ const_eval_long_running =
207
208
.label = the const evaluator is currently interpreting this expression
208
209
.help = the constant being evaluated
209
210
210
-
const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
211
-
212
211
const_eval_memory_exhausted =
213
212
tried to allocate more memory than available to compiler
214
213
215
214
const_eval_modified_global =
216
215
modifying a static's initial value from another static's initializer
217
216
218
-
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
219
-
220
-
const_eval_mutable_raw_escaping =
221
-
raw mutable pointers are not allowed in the final value of {const_eval_const_context}s
217
+
const_eval_mutable_borrow_escaping =
218
+
mutable borrows of lifetime-extended temporaries in the top-level scope of a {const_eval_const_context} are not allowed
222
219
.teach_note =
223
-
Pointers that escape into the final value of a constant or static must be immutable.
220
+
This creates a reference to a temporary that has its lifetime extended to last for the entire program.
221
+
Lifetime-extended temporaries in constants and statics must be immutable.
224
222
This is to avoid accidentally creating shared mutable state.
225
223
226
224
227
225
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
228
226
229
-
const_eval_mutable_ref_escaping =
230
-
mutable references are not allowed in the final value of {const_eval_const_context}s
231
-
.teach_note =
232
-
References that escape into the final value of a constant or static must be immutable.
233
-
This is to avoid accidentally creating shared mutable state.
234
-
235
-
236
-
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
227
+
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
237
228
238
229
const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead
239
230
@@ -437,9 +428,6 @@ const_eval_unwind_past_top =
437
428
## (We'd love to sort this differently to make that more clear but tidy won't let us...)
438
429
const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty}
439
430
440
-
const_eval_validation_const_ref_to_extern = {$front_matter}: encountered reference to `extern` static in `const`
441
-
const_eval_validation_const_ref_to_mutable = {$front_matter}: encountered reference to mutable memory in `const`
442
-
443
431
const_eval_validation_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance)
444
432
const_eval_validation_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)
445
433
const_eval_validation_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free)
@@ -479,6 +467,7 @@ const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid re
479
467
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
480
468
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
481
469
const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$expected_dyn_type}`, but encountered `{$vtable_dyn_type}`
470
+
const_eval_validation_mutable_ref_in_const = {$front_matter}: encountered mutable reference in `const` value
482
471
const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
483
472
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
484
473
const_eval_validation_null_box = {$front_matter}: encountered a null box
0 commit comments