From the type parameters proposal, there is a useful section describing how one should define a type constraint such that a type that already implements the interface via it's pointer receivers can still be used as a type parameter, for example:
type ExplainedExampleGeneric[T any] interface {
GetBool() bool
*T // non-interface type constraint element
}
type ExplainedImpl struct{ bully bool }
func (e *ExplainedImpl) GetBool() bool { return e == nil || e.bully }
func Print[T any, PT ExplainedExampleGeneric[T]](impl T) {
fmt.Println(PT(&impl).GetBool())
}
func main() {
Print[ExplainedImpl](ExplainedImpl{}) // Prints: false
}
For my use-case, I want to use this ExplainedExampleGeneric as a parameter to another generic type:
type UncharteredGeneric[T any, U any, V ExplainedExampleGeneric[U]] interface {
GetString() string
GetExplainedExampleGeneric() V
*T // non-interface type constraint element
}
type ExplainedExampleGeneric[T any] interface {
GetBool() bool
*T // non-interface type constraint element
}
This compiles, however, when trying to compile a function to utilise this UncharteredGeneric type, I get the following errors:
./prog.go:35:40: got 2 arguments but 3 type parameters
./prog.go:36:17: cannot convert &impl (value of type *T) to type PT
func UncharteredPrint[T any, U any, PT UncharteredGeneric[T, U]](impl T) { -> got 2 arguments but 3 type parameters
fmt.Println(PT(&impl).GetExplainedExampleGeneric().GetBool()) -> cannot convert &impl (value of type *T) to type PT
}
Finally, when I try to call this function, my type is unable to be inferred link to playground:
./prog.go:36:40: got 2 arguments but 3 type parameters
./prog.go:37:17: cannot convert &impl (value of type *T) to type PT
./prog.go:42:50: cannot infer PT (prog.go:36:37)
package main
import "fmt"
type UncharteredGeneric[T any, U any, V ExplainedExampleGeneric[U]] interface {
GetString() string
GetExplainedExampleGeneric() V
*T // non-interface type constraint element
}
type ExplainedExampleGeneric[T any] interface {
GetBool() bool
*T // non-interface type constraint element
}
type UncharteredImpl struct{ some string }
func (e *UncharteredImpl) GetExplainedExampleGeneric() ExplainedImpl { return ExplainedImpl{} }
func (e *UncharteredImpl) GetString() string {
if e == nil {
return ""
}
return e.some
}
type ExplainedImpl struct{ bully bool }
func (e *ExplainedImpl) GetBool() bool { return e == nil || e.bully }
func Print[T any, PT ExplainedExampleGeneric[T]](impl T) {
fmt.Println(PT(&impl).GetBool())
}
func UncharteredPrint[T any, U any, PT UncharteredGeneric[T, U]](impl T) { -> got 2 arguments but 3 type parameters
fmt.Println(PT(&impl).GetExplainedExampleGeneric().GetBool()) -> cannot convert &impl (value of type *T) to type PT
}
func main() {
Print[ExplainedImpl](ExplainedImpl{})
UncharteredPrint[UncharteredImpl, ExplainedImpl](UncharteredImpl{}) -> cannot infer PT (prog.go:36:37)
}
Any idea what I'm doing wrong? Seems like it should be possible but I'm unsure of what I'm missing here, any help would be greatly appreciated.