WhatsNew: module-qualified-class-names milestone close

Two libraries can now each declare their own class with the same
method name; type-driven dispatch resolves at the call site, with
explicit module-qualified syntax as the author's disambiguation
tool when the type alone isn't decisive.
This commit is contained in:
2026-05-13 02:50:24 +02:00
parent 1b6cbcb68b
commit 89e335a39d
+14
View File
@@ -92,3 +92,17 @@ A side effect: a function parameter declared `(own T)` whose only in-body use wa
Two modules in one workspace can each declare a type with the same bare name (for example, both declaring `type Foo`) and carry their own type-class instances — both now register under their owning modules and stay distinct. Before this round, one declaration silently overwrote the other in an internal index and the loser's instance tripped a misleading "duplicate instance" error.
Internal housekeeping in the same round: a structurally unreachable validation path was removed, and a previously implicit design decision about the type checker's overlay structure was written down.
## 2026-05-13 — Two libraries can each declare their own type class
A workspace can now have two libraries each declaring `class Show` (or `class Eq`, `class Ord`, …) with their own method, and both can ship instances for overlapping types. Before this round, the loader rejected the workspace the moment two classes anywhere declared the same method name. A workspace-global ban that was never load-bearing for correctness — just a workaround making bare method calls unambiguous.
The replacement is type-driven dispatch at the call site. When `show 42` is reached and only one class in scope declares `show`, the call resolves automatically. When two do, the checker first narrows by the argument's type (only one class might have an instance for `Int`); if that still leaves more than one, it reports the ambiguity with the candidate class names and asks the author to disambiguate via `<module>.<Class>.show 42`. A class method that happens to share a name with a free function is handled the same way: the free function wins by the existing precedence rule, but the author gets a warning so an accidental shadow doesn't pass silently.
This unblocks the deferred prelude rewire — the prelude is free to ship its own `class Show` now that it no longer collides with the 14 test fixtures that historically declared a user-class named `Show`.
The new dispatch model is now anchored in the language reference as a named subsection; the related class-reference fields (`InstanceDef.class`, `Constraint.class`, `SuperclassRef.class`) follow the same bare-for-same-module / `<module>.<Class>`-for-cross-module rule that type names already follow.
Bench all-green; the noise envelope on a tail-latency metric continues for the sixth consecutive audit and remains baseline-pristine pending a clear signal-vs-variance call.
Queue back to user-direction: the prelude-rewire milestone is ready for a fresh design pass against the new dispatch model.