'Why does Go not allow assigning one generic to another?

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 1:[1]

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. This is also true of generics instantiated with any. The type any is just another static type — alias of interface{}. It's not equal to T and it's not equal to "whatever type".

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1