diff --git a/changelog.d/8557-holders-scanner-latch-frontier.md b/changelog.d/8557-holders-scanner-latch-frontier.md new file mode 100644 index 0000000000..5a84b3a2c0 --- /dev/null +++ b/changelog.d/8557-holders-scanner-latch-frontier.md @@ -0,0 +1,15 @@ +### Fixed + +- **GC holders census: pin the two per-thread scanner latches that left `main` + red.** #8545 taught `scripts/gc_runtime_root_holders.py` to parse + `perry_thread_local!` declarations, and #8552 replaced process-global scanner + registration latches with per-thread `Cell` ones. Each change is correct + in isolation; together the census gained sight of two latches that no verdict + covered (`messaging.rs`'s `GC_SCANNER_REGISTERED`, `native_this_alias.rs`'s + `SCANNER_REGISTERED`), and an unclassified holder fails the gate by design. + + Both are idempotence flags for `ensure_*_scanner_registered()` — they store a + boolean, never an address — so they are pinned on the identity-ratcheted + frontier. That placement is forced rather than chosen: they are rule T (the + census cannot see through the type) and the gate rejects a `holders` verdict + for a rule-T declaration as stale. diff --git a/scripts/gc_runtime_root_holders.json b/scripts/gc_runtime_root_holders.json index 59988a0371..da4ad77a7a 100644 --- a/scripts/gc_runtime_root_holders.json +++ b/scripts/gc_runtime_root_holders.json @@ -703,6 +703,10 @@ "file": "crates/perry-runtime/src/map.rs", "name": "TEST_FORCE_HELPER_GC" }, + { + "file": "crates/perry-runtime/src/messaging.rs", + "name": "GC_SCANNER_REGISTERED" + }, { "file": "crates/perry-runtime/src/module_require/path_registry.rs", "name": "MODULE_PATH_REGISTRY", @@ -892,6 +896,10 @@ "file": "crates/perry-runtime/src/object/native_this_alias.rs", "name": "ALIAS_ACTIVE" }, + { + "file": "crates/perry-runtime/src/object/native_this_alias.rs", + "name": "SCANNER_REGISTERED" + }, { "file": "crates/perry-runtime/src/object/prop_plan.rs", "name": "READ_PLAN_CACHE"