@@ -125,7 +125,8 @@ pub fn intern_const_alloc_recursive<
125125
126126 // Initialize recursive interning.
127127 let base_alloc_id = ret. ptr ( ) . provenance . unwrap ( ) . alloc_id ( ) ;
128- let mut todo = vec ! [ ( base_alloc_id, base_mutability) ] ;
128+ let mut todo: Vec < _ > =
129+ intern_shallow ( ecx, base_alloc_id, base_mutability) . unwrap ( ) . map ( |prov| prov) . collect ( ) ;
129130 // We need to distinguish "has just been interned" from "was already in `tcx`",
130131 // so we track this in a separate set.
131132 let mut just_interned = FxHashSet :: default ( ) ;
@@ -142,52 +143,49 @@ pub fn intern_const_alloc_recursive<
142143 // raw pointers, so we cannot rely on validation to catch them -- and since interning runs
143144 // before validation, and interning doesn't know the type of anything, this means we can't show
144145 // better errors. Maybe we should consider doing validation before interning in the future.
145- while let Some ( ( alloc_id, mutability) ) = todo. pop ( ) {
146+ while let Some ( prov) = todo. pop ( ) {
147+ let alloc_id = prov. alloc_id ( ) ;
146148 if ecx. tcx . try_get_global_alloc ( alloc_id) . is_some ( ) {
147149 // Already interned.
148150 debug_assert ! ( !ecx. memory. alloc_map. contains_key( & alloc_id) ) ;
149151 continue ;
150152 }
151153 just_interned. insert ( alloc_id) ;
152- let provs = intern_shallow ( ecx, alloc_id, mutability) . map_err ( |( ) | {
153- ecx. tcx . dcx ( ) . emit_err ( DanglingPtrInFinal { span : ecx. tcx . span , kind : intern_kind } )
154- } ) ?;
155- for prov in provs {
156- let alloc_id = prov. alloc_id ( ) ;
157- if intern_kind != InternKind :: Promoted
158- && inner_mutability == Mutability :: Not
159- && !prov. immutable ( )
154+ if intern_kind != InternKind :: Promoted
155+ && inner_mutability == Mutability :: Not
156+ && !prov. immutable ( )
157+ {
158+ if ecx. tcx . try_get_global_alloc ( alloc_id) . is_some ( )
159+ && !just_interned. contains ( & alloc_id)
160160 {
161- if ecx. tcx . try_get_global_alloc ( alloc_id) . is_some ( )
162- && !just_interned. contains ( & alloc_id)
163- {
164- // This is a pointer to some memory from another constant. We encounter mutable
165- // pointers to such memory since we do not always track immutability through
166- // these "global" pointers. Allowing them is harmless; the point of these checks
167- // during interning is to justify why we intern the *new* allocations immutably,
168- // so we can completely ignore existing allocations. We also don't need to add
169- // this to the todo list, since after all it is already interned.
170- continue ;
171- }
172- // Found a mutable pointer inside a const where inner allocations should be
173- // immutable. We exclude promoteds from this, since things like `&mut []` and
174- // `&None::<Cell<i32>>` lead to promotion that can produce mutable pointers. We rely
175- // on the promotion analysis not screwing up to ensure that it is sound to intern
176- // promoteds as immutable.
177- found_bad_mutable_pointer = true ;
161+ // This is a pointer to some memory from another constant. We encounter mutable
162+ // pointers to such memory since we do not always track immutability through
163+ // these "global" pointers. Allowing them is harmless; the point of these checks
164+ // during interning is to justify why we intern the *new* allocations immutably,
165+ // so we can completely ignore existing allocations. We also don't need to add
166+ // this to the todo list, since after all it is already interned.
167+ continue ;
178168 }
179- // We always intern with `inner_mutability`, and furthermore we ensured above that if
180- // that is "immutable", then there are *no* mutable pointers anywhere in the newly
181- // interned memory -- justifying that we can indeed intern immutably. However this also
182- // means we can *not* easily intern immutably here if `prov.immutable()` is true and
183- // `inner_mutability` is `Mut`: there might be other pointers to that allocation, and
184- // we'd have to somehow check that they are *all* immutable before deciding that this
185- // allocation can be made immutable. In the future we could consider analyzing all
186- // pointers before deciding which allocations can be made immutable; but for now we are
187- // okay with losing some potential for immutability here. This can anyway only affect
188- // `static mut`.
189- todo. push ( ( alloc_id, inner_mutability) ) ;
169+ // Found a mutable pointer inside a const where inner allocations should be
170+ // immutable. We exclude promoteds from this, since things like `&mut []` and
171+ // `&None::<Cell<i32>>` lead to promotion that can produce mutable pointers. We rely
172+ // on the promotion analysis not screwing up to ensure that it is sound to intern
173+ // promoteds as immutable.
174+ found_bad_mutable_pointer = true ;
190175 }
176+ // We always intern with `inner_mutability`, and furthermore we ensured above that if
177+ // that is "immutable", then there are *no* mutable pointers anywhere in the newly
178+ // interned memory -- justifying that we can indeed intern immutably. However this also
179+ // means we can *not* easily intern immutably here if `prov.immutable()` is true and
180+ // `inner_mutability` is `Mut`: there might be other pointers to that allocation, and
181+ // we'd have to somehow check that they are *all* immutable before deciding that this
182+ // allocation can be made immutable. In the future we could consider analyzing all
183+ // pointers before deciding which allocations can be made immutable; but for now we are
184+ // okay with losing some potential for immutability here. This can anyway only affect
185+ // `static mut`.
186+ todo. extend ( intern_shallow ( ecx, alloc_id, inner_mutability) . map_err ( |( ) | {
187+ ecx. tcx . dcx ( ) . emit_err ( DanglingPtrInFinal { span : ecx. tcx . span , kind : intern_kind } )
188+ } ) ?) ;
191189 }
192190 if found_bad_mutable_pointer {
193191 return Err ( ecx
0 commit comments