Skip to content

Commit 3790eff

Browse files
committed
const validation: properly ignore zero-sized UnsafeCell
1 parent bc4376f commit 3790eff

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,8 +1086,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
10861086
) -> InterpResult<'tcx> {
10871087
// Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory.
10881088
if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
1089-
if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env)
1090-
{
1089+
// Unsized unions are currently not a thing, but let's keep this code consistent with
1090+
// the check in `visit_value`.
1091+
let zst = self
1092+
.ecx
1093+
.size_and_align_of(&val.meta(), &val.layout)?
1094+
.is_some_and(|(s, _a)| s.bytes() == 0);
1095+
if !zst && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env) {
10911096
if !self.in_mutable_memory(val) {
10921097
throw_validation_failure!(self.path, UnsafeCellInImmutable);
10931098
}
@@ -1131,7 +1136,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
11311136

11321137
// Special check preventing `UnsafeCell` in the inner part of constants
11331138
if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
1134-
if !val.layout.is_zst()
1139+
// Exclude ZST values. We need to compute the dynamic size/align to properly
1140+
// handle slices and trait objects.
1141+
let zst = self
1142+
.ecx
1143+
.size_and_align_of(&val.meta(), &val.layout)?
1144+
.is_some_and(|(s, _a)| s.bytes() == 0);
1145+
if !zst
11351146
&& let Some(def) = val.layout.ty.ty_adt_def()
11361147
&& def.is_unsafe_cell()
11371148
{
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//! Ensure we do not complain about zero-sized `UnsafeCell` in a const in any form.
2+
//! See <https://github.com/rust-lang/rust/issues/142948>.
3+
4+
//@ check-pass
5+
use std::cell::UnsafeCell;
6+
7+
const X1: &mut UnsafeCell<[i32; 0]> = UnsafeCell::from_mut(&mut []);
8+
9+
const X2: &mut UnsafeCell<[i32]> = UnsafeCell::from_mut(&mut []);
10+
11+
trait Trait {}
12+
impl Trait for [i32; 0] {}
13+
const X3: &mut UnsafeCell<dyn Trait> = UnsafeCell::from_mut(&mut []);
14+
15+
fn main() {}

0 commit comments

Comments
 (0)