Why does Go not allow assigning one generic to another?

Issue

Following code throws a compilation error

cannot use ExampleProps (variable of type Props[Example]) as Props[Generic] value in return statement

// Abstract
type Generic interface {
    ID() string
}

type Props[G Generic] struct{}

// Example
type Example struct {
    id string
}

func (example Example) ID() string {
    return example.id
}

var ExampleProps = Props[Example]{}

// Problem
func Problem() Props[Generic] {
    return ExampleProps
}

My question is: as Example implements Generic, why does Go not allow assigning Props[Example] to Props[Generic]?

Solution

Instantiating a generic type with different type arguments produces two new different named types.

Note that every time you supply a type argument, including in function arguments or return types, you are instantiating the generic type:

// Props is instantiated with type argument 'Generic'
func Problem() Props[Generic] {
    return ExampleProps
}

Therefore Props[Example] is just not the same type as Props[Generic] and you can’t use values of one type wherever the other one is expected. It does not matter if the types used as arguments themselves meet some condition for assignability, e.g. interfaces and implementors.

In simpler terms it’s as if you were using int where string is expected.

What you can do fix it and keep some flexibility is to instantiate Props with a type parameter — whether this makes sense or not depends on how you actually plan to use this function. Anyway, as demonstration:

// adding a field to make this a bit less contrived
type Props[G Generic] struct{ Value G }

// Props instantiated with T, adequately constrained
func Problem[T Generic](v T) Props[T] {
    return Props[T]{ Value: v }
}

func main() {
    a := Problem(Example{})
    fmt.Println(a)
}

Playground: https://gotipplay.golang.org/p/wcDOtJ6z80u

Answered By – blackgreen

Answer Checked By – Jay B. (GoLangFix Admin)

Leave a Reply

Your email address will not be published.