A frame with no slots still has a body, and the note spoke for it

"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.
This commit is contained in:
Joseph Ferano 2026-09-12 14:51:24 +07:00
parent b5d7a6e45f
commit 4e6b3f6183

View File

@ -783,13 +783,12 @@ let locals t ~frame =
(name (name
^ " is not a function this session holds; a lifted handler clause has no declaration of its own to read slot names from") ^ " is not a function this session holds; a lifted handler clause has no declaration of its own to read slot names from")
| Some fn -> | Some fn ->
if nslots = 0 then (* The two body checks come first, including for a frame
ok with no slots. "every slot in it is one the compiler made
[ ":frame " ^ Wire.quote name; ":locals ()"; ":refused ()"; up" is a claim about the body this session holds, and a
":note " zero-slot frame whose body has since been replaced by one
^ Wire.quote with slots is a frame that claim is false about. *)
"that frame records no slots; every slot in it is one the compiler made up" ] if nslots <> Array.length fn.Tast.slots then
else if nslots <> Array.length fn.Tast.slots then
error error
(Printf.sprintf (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" "%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 (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" "%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) 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 else
match bound_slots t ~frame with match bound_slots t ~frame with
| Error m -> error ("the program refused to say which slots are bound: " ^ m) | Error m -> error ("the program refused to say which slots are bound: " ^ m)