@@ -33,8 +33,9 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> {
33
33
/// A list of all encountered allocations. After type-based interning, we traverse this list to
34
34
/// also intern allocations that are only referenced by a raw pointer or inside a union.
35
35
leftover_allocations: & ' rt mut FxHashSet < AllocId > ,
36
- /// The root kind of the value that we're looking at. This field is never mutated and only used
37
- /// for sanity assertions that will ICE when `const_qualif` screws up.
36
+ /// The root kind of the value that we're looking at. This field is never mutated for a
37
+ /// particular allocation. It is primarily used to make as many allocations as possible
38
+ /// read-only so LLVM can place them in const memory.
38
39
mode: InternMode ,
39
40
/// This field stores whether we are *currently* inside an `UnsafeCell`. This can affect
40
41
/// the intern mode of references we encounter.
@@ -113,8 +114,8 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
113
114
// For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
114
115
// no interior mutability.
115
116
let frozen = ty. map_or ( true , |ty| ty. is_freeze ( ecx. tcx , ecx. param_env ) ) ;
116
- // For statics, allocation mutability is the combination of the place mutability and
117
- // the type mutability.
117
+ // For statics, allocation mutability is the combination of place mutability and
118
+ // type mutability.
118
119
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
119
120
let immutable = mutability == Mutability :: Not && frozen;
120
121
if immutable {
@@ -188,8 +189,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
188
189
}
189
190
}
190
191
191
- // ZSTs do not need validation unless they're uninhabited
192
- if mplace. layout . is_zst ( ) && !mplace . layout . abi . is_uninhabited ( ) {
192
+ // ZSTs cannot contain pointers, so we can skip them.
193
+ if mplace. layout . is_zst ( ) {
193
194
return Ok ( ( ) ) ;
194
195
}
195
196
@@ -209,13 +210,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
209
210
if let ty:: Dynamic ( ..) =
210
211
tcx. struct_tail_erasing_lifetimes ( referenced_ty, self . ecx . param_env ) . kind ( )
211
212
{
212
- // Validation will error (with a better message) on an invalid vtable pointer
213
- // so we can safely not do anything if this is not a real pointer.
214
213
if let Scalar :: Ptr ( vtable) = mplace. meta . unwrap_meta ( ) {
215
214
// Explicitly choose const mode here, since vtables are immutable, even
216
215
// if the reference of the fat pointer is mutable.
217
216
self . intern_shallow ( vtable. alloc_id , InternMode :: ConstInner , None ) ;
218
217
} else {
218
+ // Validation will error (with a better message) on an invalid vtable pointer.
219
219
// Let validation show the error message, but make sure it *does* error.
220
220
tcx. sess
221
221
. delay_span_bug ( tcx. span , "vtables pointers cannot be integer pointers" ) ;
@@ -224,7 +224,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
224
224
// Check if we have encountered this pointer+layout combination before.
225
225
// Only recurse for allocation-backed pointers.
226
226
if let Scalar :: Ptr ( ptr) = mplace. ptr {
227
- // Compute the mode with which we intern this.
227
+ // Compute the mode with which we intern this. Our goal here is to make as many
228
+ // statics as we can immutable so they can be placed in const memory by LLVM.
228
229
let ref_mode = match self . mode {
229
230
InternMode :: Static ( mutbl) => {
230
231
// In statics, merge outer mutability with reference mutability and
@@ -243,8 +244,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
243
244
}
244
245
Mutability :: Not => {
245
246
// A shared reference, things become immutable.
246
- // We do *not* consier `freeze` here -- that is done more precisely
247
- // when traversing the referenced data (by tracking `UnsafeCell`).
247
+ // We do *not* consider `freeze` here: `intern_shallow` considers
248
+ // `freeze` for the actual mutability of this allocation; the intern
249
+ // mode for references contained in this allocation is tracked more
250
+ // precisely when traversing the referenced data (by tracking
251
+ // `UnsafeCell`). This makes sure that `&(&i32, &Cell<i32>)` still
252
+ // has the left inner reference interned into a read-only
253
+ // allocation.
248
254
InternMode :: Static ( Mutability :: Not )
249
255
}
250
256
Mutability :: Mut => {
0 commit comments