Repository navigation
Trait holes: supertrait at the impl's type, pins need Equal, blanket impl error, type-named variants - #145
Merged
Conversation
…mpls, a type named like its variant
- A supertrait holds at the impl's own type, its type variables having
what the header gives them (with the supertraits of those bounds):
`trait Same for Box(a) {}` with `trait Same: Equal` is
"type 'Box(a)' implements 'Same' but does not implement supertrait
'Equal': 'a' needs 'Equal'", help "add `where a: Equal` to the
impl". A structural supertrait asks it of the variables the type's
parts are of, one with a written impl what that impl's header asks;
a bare target (`trait Same for Pair`) names its variables by
letters, help "write the impl for `Pair(a, b)`, with `where a:
Equal`". (Such programs checked and then failed, or showed a
function, or ordered maps, when run.)
- A pin needs Equal as `==` does: "the pin '^f' requires a comparable
type, got 'Fn(Int) -> Int'" at the pin; a type variable without the
bound "..., which the pin '^x' needs"; channels stay pinnable.
- `trait T for a` is an error, "trait impl target 'a' is not a
declared type" (it was skipped without a word).
- A name that is both a type and its variant (`type Box(a) { Box(a),
Empty }`) is the type before a method (`Box.default()`,
`lib.Box.default()`) and as a `type t` argument (`mk(Box)`).
- traits.md: impls of one trait at different arguments do not coexist
(one impl per type, whatever the arguments); the supertrait rule at
the impl's type; blanket impls; pins need Equal (pattern-matching.md).
Goldens (fail on 51dfe06): typecheck/traits/supertrait__at_the_impls_type,
typecheck/traits/blanket_impl__is_an_error, lang/patterns/pin__needs_equal,
lang/traits/type_named_like_its_variant__is_the_type; guards
lang/traits/supertrait__the_header_gives_it, lang/patterns/pin__compares_as_equal_does.
Removed: two goldens of the old behaviour (a lowercase impl target
checks; an enum shadowed by its variant is no type argument).
rendro
added this pull request to stack #146
October 23, 2026 11:49
B1: `let f = Greet.greet` (and `Box.default`) is a syntactic value, as `let s = string.from` is: the let is general, local, top-level and in the REPL. (The value restriction asked for a resolved name, which a method through its trait or type gets only from the checker.) B2: the VM's structural `hash` answers a Bytes value through CallMethod, as nested Bytes already did. Goldens: lang/traits/trait_call__a_method_value_is_generic, lang/traits/hash_of_bytes__through_the_trait (both fail on 51dfe06).
G1: the name of a trait's method, at a call (`Area.area(s)`, `shapes.Area.area(s)`, `Int.empty()`) or where the trait or an impl declares it, is the method: references find its declaration in the trait, every impl's method (in any module) and its calls; rename edits them all (refused for a builtin trait's method, or where the trait already has a method of the new name: new text "the trait already has a method `new`"); highlight and declaration likewise. A method name after a type is no longer taken for a use of the trait. Goldens: lsp/trait_method_references_and_rename (new), lsp/rename_by_meaning (a method's rename now edits the method).
…em; every trait of the method is named; module help keeps the other arguments The help after a value or through a type writes the trait by the name an import gave it (Area), through the alias of its module (sh.Area) or by its module path (shapes.Area), and the module of a function by its alias (l.length(xs)). When two traits in sight have the method, the help names both: "`go` is a method of trait `Aa` and of trait `Bb`: call it as `Aa.go(n)` or `Bb.go(n)`". A module function with more parameters is written with `, ..` (map.get(m, ..)). Both messages of one program spell a type the same way.
…the type in a method call and a type argument `Box.default()` and `mk(Box)` with a type `Box` and a variant `Box` of type `Other` reach the type; `Box` as a value is still the variant.
… variable that needs a bound help: write the impl for `Pair(a, b)`, with `where a: Equal, b: Equal` (and "add `where a: Equal, b: Equal` to the impl" when the header names the variables).
…ted again at its uses After `trait impl target 'a' is not a declared type`, a call of the trait's method on a type is not also "type 'Int' does not implement trait 'Shout'" (in the module of the impl; one in another module still says it).
…efault body's Self, get helps that name the supertrait
New texts:
help: `sup` is a method of supertrait `Super`: call it as `Super.sup(x)`
(for `Sub.sup(x)`, in place of a did-you-mean on the subtrait's methods)
help: add `where Self: Greet2`, or make `Greet2` a supertrait: `trait Def: Greet2`
(a default body of `Def` that needs `Self: Greet2`)
…pe; two missing fields name the type
New texts:
trait 'Area' is not in scope
help: import it: `import shapes.{ Area }`
(was: undefined variable 'Area', help: did you mean `shapes.Area`? ...)
type 'Person' has no fields 'email', 'phone'
(was: record Person has no fields 'email', 'phone')
…rted, asks nothing more of the types it leaves unknown `Greet.greet()` is the arity error alone, without "cannot infer the type this use of 'greet' needs"; so is `[1, 2] |> list.map(Greet.greet)` before `import list` in the REPL (the module error alone).
", by argument 2" for the second argument; the verifier's text is "`CallMethod` finds its method by argument 2 of 1" (changed text j).
In `3 |> Put.put(4)` the cursor at `4` is on parameter 2, for every call a pipe goes into (`list.map`, a function of the module).
… an INTERFACE token
…ue of it After `Int.` (a type of the prelude too) or `Box.`, completion lists the type's variants and the methods of its impls' traits that take no value of the type (`empty`), with their signatures.
… given now
The tuple-index and shadowed-Int cases asserted the absence of
"unknown method ...", a text no longer given anywhere; they now assert
the absence of the current generic text ("has no field '0'").
…e forms that exist now The comment lines of goldens that named receiver-form calls (`.display()`, `.compare()`, `.hash()`, `.message()`, `.encode()`, `x.show()`) name the call through the trait, interpolation or `string.from`; so do generics.md (`Stream.first(w)`), the module docs of init_order.rs and vm/encode.rs, and the fuzz corpus files that still called `e.message()`. Changed runtime text (an internal type confusion of the VM): string interpolation requires string values, got List — convert the value with `string.from` first (was: ... — call `.to_string()` or `.display()` on the value first)
…re deleted or given their purpose back Deleted: resolve__error_message_through_builtin_type and resolve__builtin_trait_method_through_builtin_type (tautologies; replaced by resolve__builtin_trait_method_not_through_a_builtin_type, the errors and helps of `io.IoError.message(e)`, `Int.compare(1, 2)`, `Int.display(1)`), round73f display_method_equals_message_for_io_error (the round74 io case says it), type_audit_regressions__receiver_method_correct_arity_accepted. Renamed: round101_polymorphic_display_method_gate__* to ..._bound_gate__*, round74 io_error_three_forms_agree to io_error_two_forms_agree, container_fn_compare polymorphic_equal_method to polymorphic_equal_bound. Given their purpose back: the forms a rewrite made identical are the pipe into a call through a trait, a method value, `string.from`, `println(t)`, a qualified trait call, `Compare.compare`/`Hash.hash` of a derived impl, or deleted where the old form has no new one (`x.equal(y)` beside `x == y`); the round88 unit-variant cases dispatch a program's trait on a unit variant; headers say what the case does.
…an impl of the trait The rename would make the impl's method named like a field, an error. New text (LSP rename refusal): `area` cannot be renamed to `r`: `Circle`, which has an impl of the trait, has a field `r`, and the rename would change what a name means
…s record is an error (T7) A dot after a value is always the field and a trait's method is called through its trait, so nothing can be read two ways (owner, 2026-10-23, reversing the Step E decision of 2026-10-10). Removed: the check (methods_named_like_fields), its code E0341 MethodNamedLikeField and its texts, RecordInfo::field_spans (only it read them), the rule's 23 goldens; the LSP rename of a trait's method to a field name is allowed again (text x of the fix round is gone with it). traits.md shows a field and a method of one name: `job.run(5)` calls the field, `Runner.run(job, 5)` the method. field_and_method__of_one_name (was field_method__what_is_no_clash) calls both, written and default methods, through a bound, on a generic record, in a closure.
Conflict: src/vm/run.rs, the interpolation failure: main's new arms
(text and its length cap) with this branch's text for a value that is
no text ("convert the value with `string.from` first").
error-codes.md loses the E0341 row (the code went with T7).
hidden_module__an_alias_names_the_module_too re-blessed: the module help
writes the module as this module imports it (`l.length(list)`).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wave 1, lane T, step 2 (stacked on #136): the four trait holes, decided by the owner on 2026-10-22.
type 'Box(a)' implements 'Same' but does not implement supertrait 'Equal': 'a' needs 'Equal', helpadd `where a: Equal` to the impl.==:the pin '^f' requires a comparable type, got 'Fn(Int) -> Int', at the pin. Channels stay pinnable.trait T for ais an error:trait impl target 'a' is not a declared type(it was accepted silently and never applied).type Box(a) { Box(a), Empty }) means the type inBox.default()and as atype aargument.Verified by an independent verifier; its findings are fixed. The owner approved every new message text on 2026-10-23. The rule that an impl method may not be named like a field of its record is dropped (owner, 2026-10-23).