@@ -125,7 +125,8 @@ pub fn intern_const_alloc_recursive<
125
125
126
126
// Initialize recursive interning.
127
127
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 ( ) ;
129
130
// We need to distinguish "has just been interned" from "was already in `tcx`",
130
131
// so we track this in a separate set.
131
132
let mut just_interned = FxHashSet :: default ( ) ;
@@ -142,52 +143,49 @@ pub fn intern_const_alloc_recursive<
142
143
// raw pointers, so we cannot rely on validation to catch them -- and since interning runs
143
144
// before validation, and interning doesn't know the type of anything, this means we can't show
144
145
// 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 ( ) ;
146
148
if ecx. tcx . try_get_global_alloc ( alloc_id) . is_some ( ) {
147
149
// Already interned.
148
150
debug_assert ! ( !ecx. memory. alloc_map. contains_key( & alloc_id) ) ;
149
151
continue ;
150
152
}
151
153
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)
160
160
{
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 ;
178
168
}
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 ;
190
175
}
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
+ } ) ?) ;
191
189
}
192
190
if found_bad_mutable_pointer {
193
191
return Err ( ecx
0 commit comments