Skip to content

proposal: spec: allow type assertion on type parameter value #49206

@SamWhited

Description

@SamWhited

Hi all,

When using the Go 1.18 generics implementation I've found myself several times wishing I had compile time type assertions. When looking to see why these didn't exist I found the FAQ entry about it, which contains the following:

We removed this facility because it is always possible to convert a value of any type to the empty interface type, and then use a type assertion or type switch on that.

I started doing this as that's what was recommended, however I quickly ran into an issue: if I accidentally asserted on the wrong thing (ie the struct instead of a field, or the wrong field, etc.) this would result in a silent failure (no error, the type switch would just fail) because anything can be stuffed into an empty interface. In one concrete example I typed the following:

switch v := (interface{})(item).(type) { …

and was having trouble figuring out why my code was failing. What I had meant to type was item.Value or something along those lines which is a generic member of the struct, however, because anything could be boxed into an interface the code happily compiled and ran, resulting in fallback behavior even though I knew the type was correct (and confusing me for quite a while until I spotted the typo).

If however compile time type switching and assertions existed this would have failed because item is not an interface type. I would have then realized my mistake and been able to fix it thanks to the nice error message. Another benefit is that at compile time the type switch or assertion could result in a compile error if one of the branches or the assertion was a value that does not meet the interface, adding a layer of compile time safety and reducing dead code, or possibly catching some accidental uses of the wrong type.

In just a few days of using generics on a real project I have run into this and similar issues several times, so I'd like to request that the lack of compile time assertions be reconsidered.

The other reason mentioned for not doing them is that it can be confusing which type we're asserting on:

Also, it was sometimes confusing that in a constraint with a type set that uses approximation elements, a type assertion or type switch would use the actual type argument, not the underlying type of the type argument

However that confusion is not reduced by using a runtime type switch as evidenced by the example later on in this section where similar confusion occurs at runtime. I believe the potential for silent failures to be worse than the potential for confusion about the types (though that is entirely anecdotal based on a very limited amount of time using the most recent proposal for anything that's not just a toy).

I will volunteer to write a proper proposal if this is something the Go team is willing to reconsider in a future version of Go.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Hold

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions