-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
Hello!
When x/tools/go/ssa is instantiating generic functions, it seems that the type parameter substitution algorithm does not successfully substitute all instances of the function's parameters when there are other parameterized types involved in an expression. This is easier to explain with two examples.
In this example, the panic occurs while processing the expression B[rune](s) while instantiating S[int].M. The type argument for B is unimportant as it's not used, but the presence of the type parameter prevents the type substitution algorithm from rewriting the underlying type of B[rune] from struct{a T} to struct{a int}, and ssa generation for the conversion subsequently panics.
convert.go
package main
type S[T any] struct {
a T
}
func (s S[T]) M() {
type A S[T]
type B[U any] A
_ = B[rune](s)
}
func main() {
S[int]{}.M()
}
$ go install golang.org/x/tools/cmd/ssadump@latest
$ ssadump -build=G convert.go
panic: in (command-line-arguments.S[int]).M[int]: cannot convert term *t0 (command-line-arguments.S[int] [within struct{a int}]) to type command-line-arguments.B[rune] [within struct{a T}]
...
In this second example, the panic occurs while processing the method expression i.M while instantiating the function foo[int]. Here golang.org/x/tools/go/ssa.(*subster).typ panics; it seems that it cannot perform chains of substitutions through a parameterized named type to get from I2[int] to I1[int] to interface { M(int) }.
method-expression.go:
package main
type I1[T any] interface {
M(T)
}
type I2[T any] I1[T]
func foo[T any](i I2[T]) {
_ = i.M
}
type S[T any] struct{}
func (s S[T]) M(t T) {}
func main() {
foo[int](I2[int](S[int]{}))
}
$ ssadump -build=G method-expression.go
panic: type param without replacement encountered
...