The account of generics catches up with the three rules it gained
The spike banner names plan.org's Types section and spec-memory.md's Generics section as the current account. Neither said anything about a literal at a type variable, about widening meeting a generic binding, or about dyn, and all three are now observable from a program -- so the account had a hole rather than an error. Filled, in spec-memory.md, in the terms a programmer meets them in. And one stale claim found and deliberately left: plan.org still lists five predicates and describes copyable? and move-only-by-default at length. spec-memory.md already records that copyable? went with the second repeal and check.ml has four. That sentence belongs to the ownership-repeal lane, so it is flagged in FIX.org rather than rewritten here.
This commit is contained in:
parent
b64770feb7
commit
56040ec6bd
14
FIX.org
14
FIX.org
@ -3490,3 +3490,17 @@ Dev-loop reload needed nothing: test_session already pins ~C-c C-c~ on a
|
|||||||
generic installing its copies, the callee side, the absence of a stale cache
|
generic installing its copies, the callee side, the absence of a stale cache
|
||||||
across two evaluations, and a redefinition that needs a copy the process was
|
across two evaluations, and a redefinition that needs a copy the process was
|
||||||
never built with.
|
never built with.
|
||||||
|
|
||||||
|
** One stale claim flagged, not touched
|
||||||
|
plan.org's Types section still lists *five* predicates and describes
|
||||||
|
~copyable?~ and "a type variable is move-only by default" at length.
|
||||||
|
spec-memory.md's Generics section already records that ~copyable?~ went with
|
||||||
|
the second repeal, and ~predicate_names~ in check.ml has four. plan.org is the
|
||||||
|
one that is behind. Left alone deliberately: it is the ownership-repeal lane's
|
||||||
|
sentence to retire, not this one's, and it is flagged here so that lane picks
|
||||||
|
it up.
|
||||||
|
|
||||||
|
spec-memory.md's Generics section gained the three rules this lane decided —
|
||||||
|
the literal under ~numeric?~, the widening boundary, and dyn — because the
|
||||||
|
spike banner names that section and plan.org's Types as the current account,
|
||||||
|
and all three are observable from a program.
|
||||||
|
|||||||
@ -301,6 +301,33 @@ Type arguments are **inferred at call sites** from the argument types; there is
|
|||||||
no explicit instantiation syntax in the first implementation. A type variable
|
no explicit instantiation syntax in the first implementation. A type variable
|
||||||
that appears only in the return type is therefore an error.
|
that appears only in the return type is therefore an error.
|
||||||
|
|
||||||
|
Three further rules about what a call site may pass, all decided 2026-09-20 and
|
||||||
|
written up in FIX.org, "Milestone 5, and the sweep behind it":
|
||||||
|
|
||||||
|
**A written number may stand where a type variable stands, under `numeric?`.**
|
||||||
|
`(defn pos? [x $t] bool {:where (numeric? $t)} (> x 0))` is the family the
|
||||||
|
feature was asked for, and the bound is what makes the `0` sound rather than
|
||||||
|
optimistic: every type `numeric?` admits is an integer or a float, and an
|
||||||
|
untyped integer constant is usable at all of them. Nothing weaker admits it —
|
||||||
|
`ordered?` admits an enum, which holds no number. A *float* literal is refused
|
||||||
|
at a type variable even under `numeric?`, because `numeric?` covers the
|
||||||
|
integers too and a float literal is never usable where an integer is wanted.
|
||||||
|
The range check belongs to each copy, not to the definition.
|
||||||
|
|
||||||
|
**Implicit widening does not cross a generic binding.** A concrete argument at
|
||||||
|
a variable an earlier argument already bound has to be that type, not merely
|
||||||
|
one that widens into it — otherwise which copy a call gets depends on which
|
||||||
|
argument was written first. Letting the pair meet at the wider type stays
|
||||||
|
available as a later loosening; nothing written under this rule would stop
|
||||||
|
compiling. An untyped literal is unaffected: it has no type of its own to keep.
|
||||||
|
|
||||||
|
**A type variable is not instantiated at `dyn`.** Two models answer "one body,
|
||||||
|
many types" and they are not rivals: this one copies per written type at
|
||||||
|
compile time, `defgeneric`/`defmethod` dispatch at run time on a value that
|
||||||
|
carries its own. A dyn argument asks the second question of the first
|
||||||
|
machinery, and the refusal says so. Whether dyn should ever flow through a
|
||||||
|
generic is open.
|
||||||
|
|
||||||
## Function values
|
## Function values
|
||||||
|
|
||||||
Three cases, split by whether the value escapes the frame that made it.
|
Three cases, split by whether the value escapes the frame that made it.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user