compiler: exclude generic methods from runtime method sets#5544
Merged
Conversation
Go 1.27 promoted "generic methods" (methods with their own type
parameters, independent of any type parameters on the receiver) out
of the GenericMethods experiment, e.g.:
func (r *Rand) N[Int intType](n Int) Int
Boxing a value of a type with such a method into an interface caused
tinygo to panic while building the runtime type's method table:
getTypeCode -> getMethodSetValue -> getTypeCodeName
getTypeCodeName's type switch has no case for *types.TypeParam, and a
generic method's Signature carries the method's own type parameters
in its parameter/result types (e.g. "Int" above), so encoding it into
a type code name panicked with "unknown type: <param name>".
This affected any package using math/rand/v2.Rand.N, including much of
the math/rand/v2 test suite, since printing or otherwise boxing a
*Rand into an interface is common.
Upstream reflect deliberately excludes generic methods from
Type.NumMethod()/Type.Method() (they can't be instantiated implicitly,
and a generic method can never satisfy an interface method), so mirror
that behavior: add isGenericMethod, which checks whether a method's
Signature has its own type parameters, and skip such methods when
building the runtime method count, method set value, and method set
in compiler/interface.go.
Fixes a panic isolated to:
package main
type T struct{}
func (t T) M[X int](n X) X { return n }
func main() {
var t T
var i interface{} = t
_ = i
}
jakebailey
reviewed
Jul 22, 2026
hasMethodSet was computed from the raw, unfiltered method set length (ms.Len() != 0), before generic methods were excluded from numMethods and the method set value. For a type whose only method is generic (e.g. "func (t T) M[X int](n X) X"), this left hasMethodSet true even though the actual (filtered) method set is empty, causing an unnecessary empty method-set global and methodSet field to be emitted for that type's type descriptor. Compute hasMethodSet from the same filtered loop that produces numMethods, so it's true only when at least one non-generic method exists.
Add compiler/testdata/go1.27.go, gated behind Go >= 1.27 (the version
that promoted generic methods out of the GenericMethods experiment),
covering both fixes from the previous two commits:
- genericMethod has a regular method and a generic method (its own
type parameter); boxing it into an interface must only include the
regular method in the runtime method set instead of panicking in
getTypeCodeName.
- onlyGenericMethod's sole method is generic, so its type code must
have hasMethodSet == false and no methodSet field at all, not an
empty one.
Verified this test panics on the pre-fix compiler/interface.go and
passes after it.
jakebailey
approved these changes
Jul 22, 2026
Member
|
Thank you for working on this @dgryski and to @jakebailey for review. Now merging. |
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.
Go 1.27 promoted "generic methods" (methods with their own type parameters, independent of any type parameters on the receiver) out of the GenericMethods experiment, e.g.:
Boxing a value of a type with such a method into an interface caused tinygo to panic while building the runtime type's method table:
getTypeCodeName's type switch has no case for *types.TypeParam, and a generic method's Signature carries the method's own type parameters in its parameter/result types (e.g. "Int" above), so encoding it into a type code name panicked with "unknown type: ".
This affected any package using math/rand/v2.Rand.N, including much of the math/rand/v2 test suite, since printing or otherwise boxing a *Rand into an interface is common.
Upstream reflect deliberately excludes generic methods from Type.NumMethod()/Type.Method() (they can't be instantiated implicitly, and a generic method can never satisfy an interface method), so mirror that behavior: add isGenericMethod, which checks whether a method's Signature has its own type parameters, and skip such methods when building the runtime method count, method set value, and method set in compiler/interface.go.
Fixes a panic isolated to: