It's not as common as unwrapping to concrete types, but still frequently used.
One place it's absolutely critical, and certainly the most common by number-of-calls even if people don't think about it, is `fmt` functions that check to see if the type implements `String() string`.
It's a little annoying but I don't think it's as bad as Java's erasure. We're still very early in idiomatic Go-with-generics so maybe we'll see a huge impact from this limitation later, but most times I see people wanting generic method parameters, they've got a design in mind which would be horribly inefficient even if it was valid. If you are going to box everything and generate lots of garbage, you might as well write Java to begin with.
For the case of coercing a specifically a function argument to a different interface, there is a solution that isn't stupidly inefficient, but it's impossible to support for the general case of coercing any interface value to a different interface. I expect 90% of the time a function coerces and interface value to a different interface, that value is one of its arguments, but to support that case for generic interfaces but not the other 10% would be a really ugly design. I think you'd also have issues with treating functions that coerce their arguments to generic interfaces as first class functions.
package p1
type S struct{}
func (S) Identity[T any](v T) T { return v }
package p2
type HasIdentity[T any] interface {
Identity(T) T
}
package p3
import "p2"
// Because parameter v might be (and in this case is) coerced into
// p2.HasIdentity[int], this function gets a type annotation in the compiler
// output indicating that callers should pass a p2.HasIdentity[int] interface
// reference for v if it exists, or nil if it doesn't, as an additional
// argument.
func CheckIdentity(v interface{}) {
if vi, ok := v.(p2.HasIdentity[int]); ok {
if got := vi.Identity(0); got != 0 {
panic(got)
}
}
}
package p4
import (
"p1"
"p3"
)
func CheckSIdentity() {
p3.CheckIdentity(p1.S{})
}
I'm not sure this approach would correctly handle the case where the function is oblivious to generics but receives an object where a generic method must be used to satisfy the interface. E.g. a function taking an `any` parameter, checking if it's an `io.Writer`, passed something with a `Write[T any]([]T) (int, error)` method. Intuitively you would expect that to "materialize" with `byte` and match. And as the FAQ says, if it doesn't, then what's the point of generic method arguments since methods exist primarily to implement interfaces?
It would be up to the caller which knows the concrete type of the value getting passed as `any` to provide an interface object with a function pointer to the concrete instantiation of `Write[T]` for T=byte. If the immediate caller also doesn't know the concrete type, it would also get that from its caller. It's ultimately very fragile, since there are definitely cases where at no point in the caller chain does anyone statically know the concrete type (like if this value is pulled from a global variable with an interface type).
I think it would be terrible to include in the language because of the inconsistencies, but it is possible to make the two examples you listed as typical cases of interface->interface coercion work with generic methods, ugly as it may be.
One place it's absolutely critical, and certainly the most common by number-of-calls even if people don't think about it, is `fmt` functions that check to see if the type implements `String() string`.
An idiom found in many data-shuffling libraries is to accept a small interface like `io.Writer`, but have fast-paths if the type also implements other methods. E.g. https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/io...
It's a little annoying but I don't think it's as bad as Java's erasure. We're still very early in idiomatic Go-with-generics so maybe we'll see a huge impact from this limitation later, but most times I see people wanting generic method parameters, they've got a design in mind which would be horribly inefficient even if it was valid. If you are going to box everything and generate lots of garbage, you might as well write Java to begin with.