@@ -1086,8 +1086,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
1086
1086
) -> InterpResult < ' tcx > {
1087
1087
// Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory.
1088
1088
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 ) {
1091
1096
if !self . in_mutable_memory ( val) {
1092
1097
throw_validation_failure ! ( self . path, UnsafeCellInImmutable ) ;
1093
1098
}
@@ -1131,7 +1136,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
1131
1136
1132
1137
// Special check preventing `UnsafeCell` in the inner part of constants
1133
1138
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
1135
1146
&& let Some ( def) = val. layout . ty . ty_adt_def ( )
1136
1147
&& def. is_unsafe_cell ( )
1137
1148
{
0 commit comments