I don't disagree with it, but I also agree that there hasn't been any good solutions proposed for generics that meet the requirements that are at the core of Go: namely, performance of the compiled program, performance of the compiler, and performance of the developer.
As for the core features of Go you mentioned, sorry again for my cynical wording, but I think they are a bit dishonest.
They stress on the performance of the program, yet being slower than C/C++ due to the usage of GC and dynamic dispatch all the time. It was even regressed in Go 1.5[1], because the new GC prefers latency to performance. So, they traded performance for something considered more important.
How about the performance of the compiler? Well, the speed of the Go 1.5 compiler is ~10% worse than the previous one, because they rewrote the compiler in Go (it was previously in C, for those who didn't know yet). Why did they do so? Because it has advantages: reduces the barrier to contribute to the compiler, improves the code quality, etc.. Yet they traded performance for something they consider to be important.
And the performance of the developer... While Go is not very terrible at developer experiences, it isn't very good either. Embracing simplicity led to lack of expressiveness, a typical example being generics. While this isn't entirely a bad thing, it is, again, a trade-off.
So they make trade-offs all the time. Then why are generics not considered to be good enough to make a trade-off? Because they think so. It is their opinion, sure, but claiming generics are impossible because performance isn't very convincing to me.
[1] http://yokohummer7.github.io/blog/2015/09/01/go-1.5-regressi...
The big difference with stuff like GC and re-writing stuff in go slowing the compiler time is that they are not inherent to the language. That stuff can and will improve. With generics if done incorrectly, it's more or less permanent. So I appreciate the conservatism there, and don't think it's fair (or accurate) to say that it's dishonest.
Actually, I think GC is inherent to the language, and that's why I listed it as one of the trade-offs that Go made (not the Go implementation made). Almost every language construct depends on GC, e.g. append(), make(), and more. Even the following innocent-looking code:
func f() *int {
a := 1
return &a
}
is GC-dependent, because it would result in a dangling pointer in non-GC languages. But the code is perfectly fine in Go because GC is inherent to the language. It is not possible to make GC optional in Go, so the performance penalty will stay there forever, only alleviated as the implementation matures (or sometimes regressed, as Go 1.5 shows), unless you use only unsafe.Pointer all the time.And I don't see how adding generics would solve the problem of being able to add a FooImpl2 to a slice of FooImpls. Java has generics and they don't allow covariant generic collections for this same reason.