Skip to content

Commit e32241d

Browse files
committed
Auto merge of #116745 - RalfJung:intern-without-types, r=<try>
const interning: decide about mutability purely based on the kind of interning, not the types we see r? `@oli-obk` this is what I meant on Zulip. For now I left the type visitor in the code; removing it and switching to a simple interning loop will mean we accept code that we currently reject, such as this ```rust const CONST_RAW: *const Vec<i32> = &Vec::new() as *const _; ``` I see no reason for us to reject such code, but accepting it should go through t-lang FCP, so I want to do that in a follow-up PR. This PR does change behavior in the following situations: 1. Shared references inside `static mut` are no longer put in read-only memory. This affects for instance `static mut FOO: &i32 = &0;`. We never *promised* that this would be read-only, and `static mut` is [an anti-pattern anyway](#53639), so I think this is fine. If you want read-only memory, write this as `static INNER: i32 = 0; static mut FOO: &i32 = &INNER;`. 2. Potentially, mutable things in a `static` are now marked read-only. That would be a problem. But I am not sure if that can happen? The code mentions `static FOO: *const AtomicUsize = &AtomicUsize::new(42)`, but that is rejected for being non-`Sync`. [This variant](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=112e930ae1b3ef285812ab404ca296fa) also gets rejected, and same for [this one](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0dac8d173a2b3099b9c2854fdad7a87c). I think we should reject all cases where a `static` introduces mutable state, except for the outermost allocation itself which can have interior mutability (and which is the one allocation where we have fully reliable type information). What I still want to do in this PR before it is ready for review it is ensure we detect situations where `&mut` or `&UnsafeCell` points to immutable allocations. That should detect if we have any instance of case (2). That check should be part of the regular type validity check though, not part of interning.
2 parents 4331c15 + 22106c3 commit e32241d

14 files changed

+476
-203
lines changed

compiler/rustc_const_eval/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, bu
438438
const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
439439
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
440440
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
441-
const_eval_validation_mutable_ref_in_const = {$front_matter}: encountered mutable reference in a `const`
441+
const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
442442
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
443443
const_eval_validation_null_box = {$front_matter}: encountered a null box
444444
const_eval_validation_null_fn_ptr = {$front_matter}: encountered a null function pointer
@@ -456,7 +456,7 @@ const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned
456456
const_eval_validation_uninhabited_enum_variant = {$front_matter}: encountered an uninhabited enum variant
457457
const_eval_validation_uninhabited_val = {$front_matter}: encountered a value of uninhabited type `{$ty}`
458458
const_eval_validation_uninit = {$front_matter}: encountered uninitialized memory, but {$expected}
459-
const_eval_validation_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in a `const`
459+
const_eval_validation_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in read-only memory
460460
461461
const_eval_write_to_read_only =
462462
writing to {$allocation} which is read-only

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,21 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
336336
let mode = match tcx.static_mutability(cid.instance.def_id()) {
337337
Some(_) if cid.promoted.is_some() => {
338338
// Promoteds in statics are allowed to point to statics.
339-
CtfeValidationMode::Const { inner, allow_static_ptrs: true }
339+
CtfeValidationMode::Const {
340+
allow_immutable_unsafe_cell: false,
341+
allow_static_ptrs: true,
342+
}
340343
}
341344
Some(_) => CtfeValidationMode::Regular, // a `static`
342-
None => CtfeValidationMode::Const { inner, allow_static_ptrs: false },
345+
None => {
346+
// In normal `const` (not promoted), the outermost allocation is always only copied,
347+
// so having `UnsafeCell` in there is okay despite them being in immutable memory.
348+
let allow_immutable_unsafe_cell = cid.promoted.is_none() && !inner;
349+
CtfeValidationMode::Const {
350+
allow_immutable_unsafe_cell,
351+
allow_static_ptrs: false,
352+
}
353+
}
343354
};
344355
ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)?;
345356
inner = true;

compiler/rustc_const_eval/src/errors.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -625,13 +625,13 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
625625

626626
PointerAsInt { .. } => const_eval_validation_pointer_as_int,
627627
PartialPointer => const_eval_validation_partial_pointer,
628-
MutableRefInConst => const_eval_validation_mutable_ref_in_const,
628+
MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable,
629629
NullFnPtr => const_eval_validation_null_fn_ptr,
630630
NeverVal => const_eval_validation_never_val,
631631
NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range,
632632
PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range,
633633
OutOfRange { .. } => const_eval_validation_out_of_range,
634-
UnsafeCell => const_eval_validation_unsafe_cell,
634+
UnsafeCellInImmutable => const_eval_validation_unsafe_cell,
635635
UninhabitedVal { .. } => const_eval_validation_uninhabited_val,
636636
InvalidEnumTag { .. } => const_eval_validation_invalid_enum_tag,
637637
UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
@@ -778,10 +778,10 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
778778
NullPtr { .. }
779779
| PtrToStatic { .. }
780780
| PtrToMut { .. }
781-
| MutableRefInConst
781+
| MutableRefToImmutable
782782
| NullFnPtr
783783
| NeverVal
784-
| UnsafeCell
784+
| UnsafeCellInImmutable
785785
| InvalidMetaSliceTooLarge { .. }
786786
| InvalidMetaTooLarge { .. }
787787
| DanglingPtrUseAfterFree { .. }

0 commit comments

Comments
 (0)