Skip to content

Commit 17327b7

Browse files
committed
separately intern the outermost alloc from the rest
1 parent 4c92a5d commit 17327b7

File tree

1 file changed

+36
-38
lines changed
  • compiler/rustc_const_eval/src/interpret

1 file changed

+36
-38
lines changed

compiler/rustc_const_eval/src/interpret/intern.rs

+36-38
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)