Skip to content

Commit c9da39f

Browse files
authored
fix(printer): recover non-builtin static/vtable alloc typing (#131)
### Summary - In `src/printer.rs`, `collect_alloc` no longer panics on non-`builtin_deref` `GlobalAlloc::Static` / `GlobalAlloc::VTable` paths. - It now attempts `get_prov_ty(ty, offset)` first, and falls back to opaque `Ty::to_val(0)` when recovery is not possible. - Existing behavior for direct `builtin_deref` pointer/reference paths is unchanged. - Added a regression test using the existing integration golden framework: - `tests/integration/programs/static-vtable-nonbuiltin-deref.rs` - `tests/integration/programs/static-vtable-nonbuiltin-deref.smir.json.expected` - minimal normalization update in `tests/integration/normalise-filter.jq` (strip unstable `def_id`). ### Context This PR was split from [stable-mir-json#129](#129) so `#129` can stay focused on closure type-table metadata. The failure mode here was assert-based panic in pre-fix code when a provenance edge reached `Static`/`VTable` through a non-`builtin_deref` container type. ### Testing Automated (local): - RED (pre-fix baseline on `origin/master`): - `make integration-test TESTS=tests/integration/programs/static-vtable-nonbuiltin-deref.rs` - Result: fails with `Allocated pointer is not a built-in pointer type` panic at `src/printer.rs:789`. - GREEN (this branch): - `make integration-test TESTS=tests/integration/programs/static-vtable-nonbuiltin-deref.rs` ✅ - `make integration-test TESTS=tests/integration/programs/assert_eq.rs` ✅ - `cargo +nightly-2024-11-29 fmt --check` ✅ - `cargo +nightly-2024-11-29 clippy -- -Dwarnings` ✅ GitHub checks: - New run for head `11180ce` is in progress.
1 parent afb5944 commit c9da39f

File tree

4 files changed

+3593
-4
lines changed

4 files changed

+3593
-4
lines changed

src/printer/mir_visitor.rs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,61 @@ fn collect_alloc(
265265
.insert(val, (opaque_placeholder_ty(), global_alloc.clone()));
266266
}
267267
}
268-
GlobalAlloc::Static(_) | GlobalAlloc::VTable(_, _) => {
269-
val_collector
270-
.visited_allocs
271-
.insert(val, (ty, global_alloc.clone()));
268+
GlobalAlloc::Static(_) => {
269+
// Keep builtin-deref behavior; recover only non-builtin-deref cases.
270+
if kind.clone().builtin_deref(true).is_none() {
271+
let prov_ty = get_prov_ty(ty, &offset);
272+
debug_log_println!(
273+
"DEBUG: GlobalAlloc::Static with non-builtin-deref type; alloc_id={:?}, ty={:?}, offset={}, kind={:?}, recovered_prov_ty={:?}",
274+
val,
275+
ty,
276+
offset,
277+
kind,
278+
prov_ty
279+
);
280+
if let Some(p_ty) = prov_ty {
281+
val_collector
282+
.visited_allocs
283+
.insert(val, (p_ty, global_alloc.clone()));
284+
} else {
285+
// Recovery failed: do not treat outer container `ty` as pointee.
286+
val_collector
287+
.visited_allocs
288+
.insert(val, (opaque_placeholder_ty(), global_alloc.clone()));
289+
}
290+
} else {
291+
val_collector
292+
.visited_allocs
293+
.insert(val, (ty, global_alloc.clone()));
294+
}
295+
}
296+
GlobalAlloc::VTable(_, _) => {
297+
// Same policy as Static: keep builtin-deref, recover non-builtin-deref.
298+
if kind.clone().builtin_deref(true).is_none() {
299+
let prov_ty = get_prov_ty(ty, &offset);
300+
debug_log_println!(
301+
"DEBUG: GlobalAlloc::VTable with non-builtin-deref type; alloc_id={:?}, ty={:?}, offset={}, kind={:?}, recovered_prov_ty={:?}",
302+
val,
303+
ty,
304+
offset,
305+
kind,
306+
prov_ty
307+
);
308+
if let Some(p_ty) = prov_ty {
309+
val_collector
310+
.visited_allocs
311+
.insert(val, (p_ty, global_alloc.clone()));
312+
} else {
313+
// Unknown is safer than wrong pointee type.
314+
val_collector
315+
.visited_allocs
316+
.insert(val, (opaque_placeholder_ty(), global_alloc.clone()));
317+
}
318+
} else {
319+
val_collector
320+
.visited_allocs
321+
.insert(val, (ty, global_alloc.clone()));
322+
}
272323
}
273324
GlobalAlloc::Function(_) => {
274325
if !kind.is_fn_ptr() {

tests/integration/normalise-filter.jq

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@
2929
( .types | map(select(.[0].FunType) | sort) )
3030
] | flatten(1) )
3131
}
32+
# drop unstable compiler-internal ids that are unrelated to this regression
33+
| walk(if type == "object" then del(.def_id) else . end)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use std::fmt::Debug;
2+
3+
static S: u8 = 7;
4+
const OBJS: [&'static dyn Debug; 1] = [&S as &dyn Debug];
5+
6+
fn main() {
7+
// Keep trait-object constant usage so both Static and VTable allocs are emitted.
8+
std::hint::black_box(OBJS[0]);
9+
}

0 commit comments

Comments
 (0)