From 4e6b3f618369456100c4d16424b221c7c262172b Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 12 Sep 2026 14:51:24 +0700 Subject: [PATCH] A frame with no slots still has a body, and the note spoke for it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "every slot in it is one the compiler made up" is a claim about the body this session holds, not about the frame, and it was answered before either body check ran — so a zero-slot frame whose body had since been replaced by one with slots got that note instead of the refusal. No values were misattributed, which is why it is not the defect just fixed, but the reason given was untrue. The count and fingerprint checks now run first and the note is the last arm. --- lib/dev.ml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/dev.ml b/lib/dev.ml index 0206371..24b2c38 100644 --- a/lib/dev.ml +++ b/lib/dev.ml @@ -783,13 +783,12 @@ let locals t ~frame = (name ^ " is not a function this session holds; a lifted handler clause has no declaration of its own to read slot names from") | Some fn -> - if nslots = 0 then - ok - [ ":frame " ^ Wire.quote name; ":locals ()"; ":refused ()"; - ":note " - ^ Wire.quote - "that frame records no slots; every slot in it is one the compiler made up" ] - else if nslots <> Array.length fn.Tast.slots then + (* The two body checks come first, including for a frame + with no slots. "every slot in it is one the compiler made + up" is a claim about the body this session holds, and a + zero-slot frame whose body has since been replaced by one + with slots is a frame that claim is false about. *) + if nslots <> Array.length fn.Tast.slots then error (Printf.sprintf "%s on the stack has %d slots and the %s this session holds has %d: the frame is running a body that has been redefined since, so every slot index here would be a guess" @@ -807,6 +806,12 @@ let locals t ~frame = (Printf.sprintf "%s on the stack was compiled from a different body than the %s this session holds: this frame's body was redefined since it was entered, so its names no longer describe its values" name name) + else if nslots = 0 then + ok + [ ":frame " ^ Wire.quote name; ":locals ()"; ":refused ()"; + ":note " + ^ Wire.quote + "that frame records no slots; every slot in it is one the compiler made up" ] else match bound_slots t ~frame with | Error m -> error ("the program refused to say which slots are bound: " ^ m)