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;