Go 1.18 Generics how to define a new-able type parameter with interface

Issue

This used to work in go1.18beta1, but not works in go1.18rc1

package main

type A struct{}

func (*A) Hello() {
    println("Hello")
}

func Create[M any, PT interface {
    Hello()
    *M
}](n int) (out []*M) {
    for i := 0; i < n; i++ {
        v := PT(new(M))
        v.Hello()
        out = append(out, v)
    }
    return
}

func main() {
    println(Create[A](2))
}

Execute will throw

./prog.go:16:21: cannot use v (variable of type PT constrained by interface{Hello(); *M}) as type *M in argument to append:
    PT does not implement *M (type *M is pointer to interface, not interface)

Seems due to this limitation:

Embedding a type parameter, or a pointer to a type parameter, as an unnamed field in a struct type is not permitted. Similarly, embedding a type parameter in an interface type is not permitted. Whether these will ever be permitted is unclear at present.

How can I do this in go1.18rc1 ?

Solution

You have to convert v back to *M again.

out = append(out, (*M)(v))

The error you got is about assignability. In fact the quote in your question doesn’t forbid embedding a pointer type in an interface . Both M and PT are different named type parameters and you can’t assign one to the other without explicit conversion.

The conversion instead is valid because all types in PT’s type set (only *M) are convertible to *M.

Answered By – blackgreen

Answer Checked By – Clifford M. (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.