v: Structured generic receiver patterns#27079
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4817e91eb5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| for method in methods { | ||
| receiver_generic_names := | ||
| table.structured_receiver_generic_pattern_names(method.receiver_type) | ||
| if receiver_generic_names.len == 0 || receiver_generic_names.len != method.generic_names.len { |
There was a problem hiding this comment.
Match structured receivers even with extra method generics
Structured receiver methods are skipped whenever the number of receiver-bound placeholders differs from method.generic_names.len, but parser logic appends method-level generics to method.generic_names (for example fn (b Box[[]T]) map[U](...)). In that valid case, receiver_generic_names.len is 1 while method.generic_names.len is 2, so this branch always continues and the method is never discovered, producing an unknown method error for calls that should compile.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8ca5074b5f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| match sym.info { | ||
| Struct { | ||
| if sym.info.concrete_types.len > 0 { | ||
| parent_idx := if sym.info.parent_type != 0 { | ||
| sym.info.parent_type.clear_flag(.generic).idx() | ||
| } else if sym.parent_idx != 0 { | ||
| sym.parent_idx |
There was a problem hiding this comment.
Handle aliases in structured receiver matching
Structured receiver lookup now relies on receiver_generic_types, but this helper only matches Struct, Interface, SumType, and GenericInst. For alias receivers (e.g. type IntListExpect = Expect[[]int]), it returns none, so find_structured_receiver_method_with_types never sees the concrete generic arguments and calls like IntListExpect{...}.first_or(...) fall through to unknown method even though aliases normally inherit parent methods. This makes the new structured-receiver feature unavailable through type aliases.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
This has been addressed in the latest patch. Direct aliases such as type IntListExpect = Expect[[]int] are now handled by structured receiver lookup, and regression tests were added for array aliases, map aliases, mixed receiver patterns, and exact-method precedence through aliases.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6d601c89dc
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if sym.info is Alias { | ||
| return t.receiver_generic_types(sym.info.parent_type.derive(typ)) |
There was a problem hiding this comment.
Unwrap alias chains for structured receiver lookup
actual_receiver_generic_types only unwraps a single alias layer (Alias -> parent_type) before giving up, so structured receiver methods stop resolving for alias-of-alias types (for example type B = A where A = Expect[[]int]). In that case method calls on B can incorrectly fail with unknown method even though aliases should inherit the same receiver methods as the underlying type. This is introduced by the new alias fallback path and can be fixed by recursively unwrapping aliases (or looping until a non-alias symbol) before matching receiver generics.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
I think this one is not currently reachable: V rejects alias-to-alias declarations before method lookup (type B = A where A is already an alias). I tried adding a regression test for that shape, but it fails earlier with the existing alias rule, so I kept the patch limited to direct aliases only.
|
The branch should now be ready for final review. ( gitbot is happy! ) The first P2 was fixed by supporting structured receiver methods with extra method-level generics. For the second P2, direct aliases are now handled and covered by regression tests, including the Cgen exact-method precedence cases. |
2d90972 to
826aae7
Compare
Multi level aliases will never be allowed |
@medvednikov : Understood, thanks for confirming. That is consistent with the current PR scope: I did not try to support multi-level aliases. I was only clarifying the P2 raised by the GitHub review bot, since it mentioned alias chains. The added handling is only for direct aliases that V already accepts today, such as |
|
What is the purpose of this? |
|
The purpose is not to shorten code at the expense of explicitness. It allows a generic wrapper to expose methods only when its inner type has a specific structure. The constraint is written directly in the receiver type, so it is explicit and checked by the compiler. So the developer does not have to guess the inner workings of This does not change existing V behavior and it does not force anyone to use generics. If a project prefers only fully concrete receiver methods, it can simply keep doing that. |
It's the same with C++: you aren't forced to use that 'multi-layered academic masturbation' with templates. 👎 The language should be simplified and redundant features removed, but you guys are doing the opposite by adding even more. |
|
I think this is now more a general language philosophy discussion than a review of this specific PR. For me, this is not the right place for that discussion; there are dedicated channels for language design debates. |
|
No, this is precisely the place to discuss what you are doing to the language, similar to how C++ began to bloat and turned into a dead language. And if this pull request is accepted, I don't see the point of staying with this language. |
Summary
This PR implements structured generic receiver patterns for generic methods.
The original request was about allowing methods like
Expect[[]T], so a method can apply only when the wrapped generic type is an array. This PR generalizes that idea slightly: method receivers can now use structured type patterns such as arrays and maps, and the checker can infer the inner generic parameters from the concrete receiver type.Dependency Note
This PR depends on:
The branch is intentionally stacked on top of those fixes. It should not be merged as a standalone change before those PRs are in
main, because this feature builds on the generic/cgen correctness work from that stack.After those prerequisite fixes are merged, I think this PR would be worth reviewing fairly early before more generic-receiver work diverges around it. It touches deep parser/type-table/checker/method-resolution behavior, so having this baseline reviewed and settled should make later work easier and safer.
What This Enables
This allows generic methods to bind type parameters from structured receiver types.
For example:
With this,
Expect[[]int]bindsT = int, whileExpect[[]string]bindsT = string.Nested array elements are also handled structurally:
Maps are supported too:
So:
Behavior Rules
This PR keeps the feature deliberately scoped:
Expect[[]T]matches dynamic arrays.Expect[map[K]V]matches maps.Expect[T]continue to work.map[K]Kwithmap[string]intare rejected.voidptris not allowed to bind into these receiver patterns; users should cast to an explicit V type first.Explicit Non-Goals
This PR does not implement the original
[]T{}syntax in type position. That remains invalid syntax.It also does not implement fixed-size array receiver patterns such as:
That needs a separate design decision because
Nis a compile-time integer binding, not a normal type binding.Implementation Notes
The patch adds structured receiver pattern discovery and matching in the parser/type-table/checker path, then uses that information during method lookup and generic binding.
The goal is to keep the feature focused on method receiver type matching, without turning it into a broader generic overloading redesign.
Tests
Added coverage for:
voidptrrejection diagnostics;[]T{}receiver syntax remaining invalid.Validation run locally:
vlib/v/tests/genericscompiler_errorsfilters for generic/method/structured receiver casesvlib/v/parservlib/v/checkervlib/v/gen/cfmt -verifygit diff --checkFix #22979