Kaynağa Gözat

generics: lock two-formal instantiation (it worked; my earlier repro was incomplete)

The reported multi-formal link failure was a test-authoring gap: an
instantiation needs BOTH a DEFINITION and an IMPLEMENTATION refinement
(the single-formal tests always ship both). With both, Pair(T,U) binds
both parameters correctly. Added PairProg suite test (exit 73) and
corrected the generics summary; noted the real (UX) gap: a def-only
refinement links with no compile-time diagnostic.
Eric Streit 1 gün önce
ebeveyn
işleme
994e448bfb

+ 2 - 0
compiler/run_tests.sh

@@ -279,6 +279,8 @@ expect_run_files TAst 42 \
   t_ast.mod
 expect_run_files GenericProg 42 \
   g_ident.def g_ident.mod g_intid.def g_intid.mod g_prog.mod
+expect_run_files PairProg 73 \
+  g_pair.def g_pair.mod g_intchar.def g_intchar.mod g_pair_prog.mod
 expect_run_files WrapProg 42 \
   ../runtime/syslib/SysShim.def ../runtime/syslib/SysShim.mod \
   ../stdlib/iochan.def ../stdlib/iochan.mod \

+ 2 - 0
compiler/tests/g_intchar.def

@@ -0,0 +1,2 @@
+DEFINITION MODULE IntChar = Pair(INTEGER, CHAR);
+END IntChar.

+ 2 - 0
compiler/tests/g_intchar.mod

@@ -0,0 +1,2 @@
+IMPLEMENTATION MODULE IntChar = Pair(INTEGER, CHAR);
+END IntChar.

+ 4 - 0
compiler/tests/g_pair.def

@@ -0,0 +1,4 @@
+GENERIC DEFINITION MODULE Pair (T : TYPE; U : TYPE);
+PROCEDURE First(x : T; y : U) : T;
+PROCEDURE Second(x : T; y : U) : U;
+END Pair.

+ 6 - 0
compiler/tests/g_pair.mod

@@ -0,0 +1,6 @@
+GENERIC IMPLEMENTATION MODULE Pair;
+PROCEDURE First(x : T; y : U) : T;
+BEGIN RETURN x END First;
+PROCEDURE Second(x : T; y : U) : U;
+BEGIN RETURN y END Second;
+END Pair.

+ 8 - 0
compiler/tests/g_pair_prog.mod

@@ -0,0 +1,8 @@
+MODULE PairProg;
+// Two-formal generic instantiation, both type parameters used and
+// bound: IntChar = Pair(INTEGER, CHAR).  Exit 7 + ORD("B") = 73.
+FROM IntChar IMPORT First, Second;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := First(7, "A") + ORD(Second(1, "B"))
+END PairProg.

+ 29 - 11
docs/summary_generics-2026-10-15.md

@@ -14,23 +14,41 @@ bound to the actuals (`SymTab.EnterTypeParamBound`, `Reenter`; driver
 registry maps generic name → file; the abstract template is never
 emitted). Re-verified live: `FROM IntId IMPORT Id; Id(42)` → exit 42.
 
-## Fresh finding: multiple formals parse but do not link
+## CORRECTED 2026-10-16 — multi-formal instantiation *works*
 
-Probed 2026-10-15 (not in the suite):
+The "fresh finding" that a two-formal generic fails to link was **my
+incomplete test**: I supplied only a *definition* refinement
+(`X = M(...)`) and no *implementation* refinement
+(`IMPLEMENTATION MODULE X = M(...)`), so the instance had no body to
+emit (the single-formal tests always ship both `g_intid.def` and
+`g_intid.mod`).  With both refinements, `Pair(T, U)` instantiates
+correctly, using **both** type parameters:
 
 ```modula2
 GENERIC DEFINITION MODULE Pair (T : TYPE; U : TYPE);
-PROCEDURE First(x : T; y : U) : T; ...
-DEFINITION MODULE IntChar = Pair(INTEGER, CHAR); ...
+PROCEDURE First(x : T; y : U) : T;
+PROCEDURE Second(x : T; y : U) : U;
+END Pair.
+DEFINITION/IMPLEMENTATION MODULE IntChar = Pair(INTEGER, CHAR);
 ```
 
-Compiles (`Parsed correctly`) but **fails at link**: undefined
-`First_4`. The emitted `.ssa` references `First_4` once (call site) and
-defines no such function — the implementation unit's instantiation
-drops (or misnames) the body when there is more than one formal. The
-inc2 doc says multiple formals are "threaded but only a single `T` is
-exercised": threading covers parse, not emit. Repro files (throwaway,
-not committed): `/tmp/opencode/g2*.mod`.
+`First(7, "A") + ORD(Second(1, "B"))` compiles, links and returns 73.
+Locked as the suite test `PairProg` (`g_pair.*`, `g_intchar.*`,
+`g_pair_prog.mod`).  Suite **202/202**.
+
+Real (smaller) gap: if only the *definition* refinement is given, the
+module compiles clean but the link fails with no compile-time
+diagnostic.  Worth a driver-level "refinement has a definition but no
+implementation" warning — not a correctness bug, a UX one.
+
+## Still open (unchanged from inc2)
+
+- Increment 3: const/procedure parameters, constraints.
+- `GENERIC CLASS`; generics with a program module.
+- Instance dedup (each refinement re-instantiates today).
+- A refinement must supply both a definition and an implementation.
+- Ordering rule stands: refinement file after the generic's file,
+  generic def before its impl.
 
 ## Still open (unchanged from inc2)