From ea67e058bf09800d4a9afa9a753bbf64249fdbf7 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 25 Sep 2026 16:15:40 +0700 Subject: [PATCH] A generic over a generic struct calls another at the same struct variables, and a struct copy is a map key and a function-value parameter on both backends --- lib/check.ml | 4 ++-- test/programs/generic-struct.flan | 19 +++++++++++++++++++ test/test_acceptance.ml | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/check.ml b/lib/check.ml index 59e1ba1b..feb08cd9 100644 --- a/lib/check.ml +++ b/lib/check.ml @@ -2502,11 +2502,11 @@ let rec bind_ty ?(widen = false) ?(ro = true) subst (pat : Types.t) bind_ty ~ro:false subst (Types.Var v) (Types.Len n) && inner p a (* A struct copy at variables against a copy of the same template: each argument against its own. *) - | Types.Named p, Types.Named a when not (String.equal p a) -> + | Types.Named p, Types.Named a -> (match Hashtbl.find_opt struct_apps p, Hashtbl.find_opt struct_apps a with | Some (g, ps), Some (h, as_) when String.equal g h -> List.length ps = List.length as_ && List.for_all2 inner ps as_ - | _ -> false) + | _ -> Types.fits ~expected:pat ~actual:arg) (* Nothing generic left on the pattern side: this is ordinary type equality, and [Never] fits anywhere exactly as it does elsewhere. *) | p, a -> Types.fits ~expected:p ~actual:a diff --git a/test/programs/generic-struct.flan b/test/programs/generic-struct.flan index 564f804e..f080c4e4 100644 --- a/test/programs/generic-struct.flan +++ b/test/programs/generic-struct.flan @@ -19,6 +19,11 @@ true) false)) +;; One generic over the struct calling another at its own variables. +(defn append-all! [s (Ptr (Small $n $t)) xs [$t]] () + (dotimes [i (length xs)] + (append! s (at xs i)))) + (defn pop! [s (Ptr (Small $n $t))] (Option $t) (if (= (.count s) 0) None @@ -53,6 +58,11 @@ ;; A template naming another at its own parameters. (defstruct Twice [x (Small $m $u) y (Small $m $u)]) +;; A copy as a map key, and a named function over one handed where a +;; function value is wanted. +(defn pair-sum [p (Pair i32)] i32 (+ (.a p) (.b p))) +(defn apply-to [f (Fn [(Pair i32)] i32) p (Pair i32)] i32 (f p)) + ;; A length variable straight on an array parameter. (defn len-of [a [$k $e]] i32 k) @@ -86,4 +96,13 @@ (push v (Pair 5 6)) (println (.b (at v 0))) (free v)) + (let [t (the (Small 5 i64) (zeroed)) + xs (the [3 i64] [1 2 3])] + (append-all! (addr t) (slice xs)) + (println (total (addr t)) (.count t))) + (let [m (map-new (Pair i32) i32)] + (put m (Pair 1 2) 12) + (put m (Pair 3 4) 34) + (println (get m (Pair 3 4)) (get m (Pair 2 1)) (apply-to pair-sum (Pair 7 8))) + (free m)) 0)) diff --git a/test/test_acceptance.ml b/test/test_acceptance.ml index d9921546..a61d9c18 100644 --- a/test/test_acceptance.ml +++ b/test/test_acceptance.ml @@ -3472,7 +3472,7 @@ let () = and each read used to make the call again. *) let generic_struct_out = "60 3 4\nfalse 7.5 3\n(some 3.5) (some 2.5) 1\n2 1 2.5 1.5\n6\n\ - 0 1 2\n3 2\n6\n" + 0 1 2\n3 2\n6\n6 3\n(some 34) none 15\n" in outputs "generic structs" "programs/generic-struct.flan" generic_struct_out; outputs ~x86:true "generic structs, --x86" "programs/generic-struct.flan"