@@ -33,8 +33,9 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> {
3333    /// A list of all encountered allocations. After type-based interning, we traverse this list to 
3434/// also intern allocations that are only referenced by a raw pointer or inside a union. 
3535:  & ' 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. 
3839:  InternMode , 
3940    /// This field stores whether we are *currently* inside an `UnsafeCell`. This can affect 
4041/// the intern mode of references we encounter. 
@@ -113,8 +114,8 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
113114        // For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume 
114115        // no interior mutability. 
115116        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. 
118119        // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere. 
119120        let  immutable = mutability == Mutability :: Not  && frozen; 
120121        if  immutable { 
@@ -188,8 +189,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
188189            } 
189190        } 
190191
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 ( )  { 
193194            return  Ok ( ( ) ) ; 
194195        } 
195196
@@ -209,13 +210,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
209210            if  let  ty:: Dynamic ( ..)  =
210211                tcx. struct_tail_erasing_lifetimes ( referenced_ty,  self . ecx . param_env ) . kind ( ) 
211212            { 
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. 
214213                if  let  Scalar :: Ptr ( vtable)  = mplace. meta . unwrap_meta ( )  { 
215214                    // Explicitly choose const mode here, since vtables are immutable, even 
216215                    // if the reference of the fat pointer is mutable. 
217216                    self . intern_shallow ( vtable. alloc_id ,  InternMode :: ConstInner ,  None ) ; 
218217                }  else  { 
218+                     // Validation will error (with a better message) on an invalid vtable pointer. 
219219                    // Let validation show the error message, but make sure it *does* error. 
220220                    tcx. sess 
221221                        . 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
224224            // Check if we have encountered this pointer+layout combination before. 
225225            // Only recurse for allocation-backed pointers. 
226226            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. 
228229                let  ref_mode = match  self . mode  { 
229230                    InternMode :: Static ( mutbl)  => { 
230231                        // In statics, merge outer mutability with reference mutability and 
@@ -243,8 +244,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
243244                            } 
244245                            Mutability :: Not  => { 
245246                                // 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. 
248254                                InternMode :: Static ( Mutability :: Not ) 
249255                            } 
250256                            Mutability :: Mut  => { 
0 commit comments