From d9b035be3cbdd55f5e2eae0e63543a4101cdc35e Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 11 Sep 2026 18:01:23 +0700 Subject: [PATCH] Two collapsed line continuations, and a branch that could not fire The extern-boundary refusal and a restart-case one each had a run of spaces mid-sentence where an OCaml line continuation had been lost. The textures lane found the first while reading the FFI rules; the second was mine, from the same editing mistake in the same week. The restart-case one turned out to be unreachable as well. Each clause is checked with the type the form has already settled on, so a clause that disagrees is refused by expect where it is written - the dedicated message could only have fired if that check did not, and it does. Removed rather than reworded; a message nothing can produce is worse than no message, because the next person tries to work out what reaches it. --- .gitignore | 1 + lib/check.ml | 16 ++++++---------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index f5e5ab7..4b6b173 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ old-ocaml/ /calc-me /sand /conditions-play +.claude/ diff --git a/lib/check.ml b/lib/check.ml index 4fb170e..2be2aa2 100644 --- a/lib/check.ml +++ b/lib/check.ml @@ -652,16 +652,11 @@ and check_restart_case ctx ?want loc body clauses = if List.mem c.Ast.rname !seen then fail c.Ast.rloc "this restart-case offers %s twice" c.Ast.rname; seen := c.Ast.rname :: !seen; + (* Each is checked against what the form has settled on so far, so a + clause that disagrees fails where it is written. The first one to + produce a value is what settles it when nothing outside did. *) let b = block ctx ?want:!ty c.Ast.rloc c.Ast.rbody in - if b.Tast.ty <> Types.Never then begin - match !ty with - | None -> ty := Some b.Tast.ty - | Some t when not (Types.fits ~expected:t ~actual:b.Tast.ty) -> - fail c.Ast.rloc - "the %s clause has type %s but this restart-case has type %s — every clause and the body must agree, since the form yields whichever of them ran" - c.Ast.rname (Types.to_string b.Tast.ty) (Types.to_string t) - | Some _ -> () - end; + if !ty = None && b.Tast.ty <> Types.Never then ty := Some b.Tast.ty; { Tast.rname_id = type_id c.Ast.rname; rname = c.Ast.rname; rbody = [ b ] }) clauses @@ -1338,7 +1333,8 @@ let collect env (decls : Ast.decl list) = | Types.String | Types.Slice _ when what = "a parameter" -> () | _ -> fail loc - "%s of %s is %s, which cannot cross to C directly — pass (Ptr %s) and let the shim read it" what fn.Ast.name + "%s of %s is %s, which cannot cross to C directly — pass \ + (Ptr %s) and let the shim read it" what fn.Ast.name (Types.to_string t) (Types.to_string t) in List.iter (crossable "a parameter") params;