From 8333ba017d083d40b7ca0bbce059ef7741b44f8a Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 26 Sep 2026 18:06:29 +0700 Subject: [PATCH] A literal local read as a typed array's element takes that element's type, and the Option str refusal test names str. --- lib/check.ml | 11 ++++++++++- test/programs/autowrap.fln | 6 ++++++ test/test_acceptance.ml | 2 +- test/test_flan.ml | 4 ++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/check.ml b/lib/check.ml index da0617d2..44a9d7e1 100644 --- a/lib/check.ml +++ b/lib/check.ml @@ -9863,8 +9863,17 @@ and check_the ctx ~want loc (t : Ast.texpr) (v : Ast.expr) = | _ -> ty in let is_nil = match v.Ast.e with Ast.Var "nil" -> true | _ -> false in + (* Quietly: what [v] is on its own terms is not a use of a literal local + inside it — [[x]] read with no want would pin x at its guess, and the + annotation's want below is the use that says what x is. *) + let own_ty () = + let was = !lit_quiet in + lit_quiet := true; + Fun.protect ~finally:(fun () -> lit_quiet := was) (fun () -> + probe ctx loc (fun () -> (check ctx v).Tast.ty)) + in if ty <> Types.Dyn && not is_nil - && probe ctx loc (fun () -> (check ctx v).Tast.ty) = Some Types.Dyn + && own_ty () = Some Types.Dyn (* A keyword naming one of an enum's members is that member at the enum's type, not a dyn: [let d: Dir = :north]. *) && not (match ty, v.Ast.e with Types.Enum _, Ast.Kw _ -> true | _ -> false) diff --git a/test/programs/autowrap.fln b/test/programs/autowrap.fln index ef62defb..a63a82a6 100644 --- a/test/programs/autowrap.fln +++ b/test/programs/autowrap.fln @@ -127,6 +127,12 @@ fn main() let lv = 200 let wv: u8 = lv println(wu ?? 0, wv) + ;; and from a typed array's element, with or without an Option + let la2 = 3 + let xa: [1 i64] = [la2] + let lb2 = 3 + let xb: [2 i64?] = [lb2, None] + println(la2 * 1000000000, lb2 * 1000000000, xa[0], xb[0] ?? 0) ;; None first in an if, as in a match let e1 = if x > 1 then None else 5 let e2 = if x > 1 then 5 else None diff --git a/test/test_acceptance.ml b/test/test_acceptance.ml index e2328216..6d81ae30 100644 --- a/test/test_acceptance.ml +++ b/test/test_acceptance.ml @@ -2279,7 +2279,7 @@ let () = ("autowrap.fln", "-1\n5 4 2\n7 8 -1\n3 4\n7\n1 0 4\n5\n2 6 0\n2 -1 -1 2\n4\n-1 3 0\n\ some some some none\nsome some some none none\n1 6 -1 -1\n1\n9 8 3 5\n\ - 4000000000 4000000000 4 4\n4 4000000000\n3.5 3.5 7 7\n200 200\n-1 5\n1 0\n10\n"); + 4000000000 4000000000 4 4\n4 4000000000\n3.5 3.5 7 7\n200 200\n3000000000 3000000000 3 3\n-1 5\n1 0\n10\n"); (* x? tests and narrows, e? as g names what it found (decision 133). *) ("presence.fln", "true false true\n6\n-1\n3\n101 209 0\n11\n42\n2\nabsent\n6\nfalse true\n3\n6\n15\n"); ("presence-dyn.fln", "true false\n103 209 0\nno pet\nann\n3 2\n") ]; (* The pipe (decision 137): chains, multi-line, qualified, dyn, and the diff --git a/test/test_flan.ml b/test/test_flan.ml index 0889c686..b1170336 100644 --- a/test/test_flan.ml +++ b/test/test_flan.ml @@ -8413,8 +8413,8 @@ let () = ~needle:"expected (Option i32), found str" "(defn f [] (Option i32) \"no\")\n(defn main [] ())"; rejects_check "a literal that does not fit is refused at the Option" - ~needle:"expected (Option string), found the integer literal 5" - "(defn f [] (Option string) 5)\n(defn main [] ())"; + ~needle:"expected (Option str), found the integer literal 5" + "(defn f [] (Option str) 5)\n(defn main [] ())"; rejects_check "a narrowing is not wrapped" ~needle:"expected (Option i32), found i64" "(defn f [x i64] (Option i32) x)\n(defn main [] ())"; rejects_check "no wrap inside a container" ~needle:"expected (Vec (Option i32)), found (Vec i32)"