;; A generic whose function parameter binds the type variable, which is the ;; shape a name now has to reach: a defn's address carries (CFn [i32] i32), ;; and (apply2 bump 1) has to bind $t from it and then widen the argument. ;; ;; Both halves are here because they fail apart. The binding is Check's ;; bind_ty, which runs inside generic_call and decides the instantiation; the ;; widening is the catch-up pass at the end of the same function, because a ;; parameter that still mentioned a variable was checked with no expectation ;; at all and expect never saw the pair. Get the first without the second and ;; the call site hands one word to an instance that declares two. ;; ;; The prelude does not cover this and that is worth saying: its higher-order ;; functions bind $t from an *earlier* argument, so the parameter is already ;; concrete by the time the function value is reached, and (map-in-place s ;; double) never walks this path at all. ;; ;; The CFn half is new rather than restored: a matching bare address against ;; a (CFn [$t] $t) parameter had no arm either, and fell through to plain ;; equality. (defn apply2 [f (Fn [$t] $t) x $t] $t (f (f x))) (defn applyc [f (CFn [$t] $t) x $t] $t (f (f x))) (defn bump [n i32] i32 (+ n 1)) (defn twice [x f64] f64 (* x 2.0)) (defn main [] i32 (println (apply2 bump 1)) (println (applyc bump 1)) ;; A second instantiation, so the two copies are really two and the thunk ;; the first one minted is not reused at the wrong signature. (println (apply2 twice 1.5)) 0)