Coming back at this after more thought & exploration. The fundamental problem I see is it introduces complexity, but no value.
Say
`type I interface {...}`
`type S(type T I) struct {T}`
Then the generic S (before instantiating with a particular T) may implement any interface, e.g. in any method on S or any other generic code using S, you may have
`_, ok := (interface{}(S(...){})` ).(Whatever)`
and the result of ok depends on what T is used. Without embedding, that is strue of T but not S.
# What value did this add?
- You can call methods listed in I directly, e.g. if method Foo is in listed I, you can do s.Foo().
=> without embedding using s.I.Foo() is hardly a change.
- You can implement interfaces based on method listed in I directly, e.g. if method Foo is listed in I and characterises interface Fooer, you can do Fooer(s).
=> without embedding, you can do Fooer(s.I) or if you actually want s in the interface, write a generic method Foo in S and keep Fooer(s).
- You can implement interfaces based on method NOT listed in I directly, e.g. if method Foo is NOT listed in I, but is defined in some T and characterises interface Fooer, you can do Fooer(s) (for s := S(T){...}).
=> without embedding, you can't do this. You can do Fooer(s.I), or create a new type for this specificT, `type X S(T)`, and implement method Foo, but let's assume that neither is acceptable. How realistic / in what circumstances do you want this? If you require a struct to have a method not listed in any contract but present in the type that happens to be embedded on this instance of the generic, and want it to be assigned to an interface that uses that method but won't accept either the embedded field in the interface, nor a separate type derived from it with the additional method, I'd say you need to re-evaluate your requirements because you are not following any moderatly sensible standards, or at the very least accept you are doing something wild and can't use generics for it.
# What did this cost?
- Complexity => the possibility of there being more methods available in a struct than listed in its definition is in itself one more thing to think about.
- Refactoring => an embedding can't be refactored without a breacking change (can't change `type S(type T I) struct {T}` to `type S(type T I) struct {T}` + methods in I), since users may be relying on methods not present in I.
- Limits to Tooling: without embedding, `_, ok := (interface{}(S(...){})` ).(Whatever)` above may always be false and the tooling may be able to identify and flag that, with embedding there is nothing it can do since it may always be true.
# No arbitrary restrictions
"our hope is to make generic types work as much like ordinary types as possible, without arbitrary restrictions"
=> this is indeed a restriction, and I don't know how much that weights in the go team's mind regarding future features, etc. But on the other hand even allowing embedding in generics isn't quite as pre-generics go either, after all you are embedding using the generic's type name (in my example, T) and not the name of the actuall type T is instantiated with. In other words, the type produced can't be replicated without generics. Banning embedding you limit slightly the types you can produce, but at least those that are allowed are valid pre-generic go types.
And of course there is also a 'delay decision' argument here: if embedding is banned, it can be added later. If it is allowed, the decision is final.
I do not claim anything dramatic about this feature's significance, like generics with fail if embedding is allowed, but also generics will not fail because they weren't. So if there is no strong reason for, and there are some reasons against, it seems to me the best decision is to ban at first and re-evaluate later.