Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Assigning a value literal to a struct field of a generic type without running into an IncompatibleAssign error

This is fine:

type constraint interface {
    ~float32 | ~float64
}

type foo[T constraint] struct {
    val T
}

func (f *foo[float64]) setValToPi() {
    f.val = 3.14
}

However, if I change constraint to also include int types, I run into an error:

type constraint interface {
    ~float32 | ~float64 | ~int
}

type foo[T constraint] struct {
    val T
}

func (f *foo[float64]) setValToPi() {
    f.val = 3.14 // IncompatibleAssign: cannot use 3.14 (untyped float constant) as float64 value in assignment
}

Why do constraints that include types that don’t belong to the same "type group" cause this error, and how should I deal with it?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

This syntax:

func (f *foo[float64]) setValToPi() {
    // ...
}

Is simply a method declaration. It does not instantiate the generic type foo. The identifier float64 you have within square brackets is the name of the type parameter. It could be T, as in the type definition, just as well.

It’s like you wrote:

type foo[float64 constraint] struct {
    val float64
}

Since float64 is a predeclared identifier, you can shadow it with a type parameter name.

So within the method setValToPi, the only known information about the type of val is that it is constrained to constraint, e.g. the union of ~float32 | ~float64 | ~int.

If you change the method declaration to:

func (f *foo[T]) setValToPi() {
    // ...
}

You will get the same error with T instead:

cannot use 3.14 (untyped float constant) as T value in assignment

And the error is given by the fact that 3.14 (an untyped floating-point constant) can’t be always assigned to all possible instances of foo[T], specifically the one where T is indeed ~int.

Playground with the float64 identifier as type param: https://gotipplay.golang.org/p/1EuAsSKdihK

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading