The conclusion is pretty weird to me.<p>Go <i>does</i> rely on monomorphization for generics, just like C++ and Rust. The only difference is that this is an implementation detail, so Go can group multiple monomorphizations without worrying about anything else [1]. This form of hybrid monomorphization is being increasingly common, GHC does that and Rust is also trying to do so [2], so nothing special for Go here.<p>On the other hand, explaining variance as a lifted polymorphism is---while not incorrect per se---also weird in part because a lack of variance is at worst just an annoyance. You can always make an adapter to unify heterogeneous types. Rust calls it `Box<dyn Trait>`, Go happens to call it an interface type instead. Both languages even do not allow heterogeneous <i>concrete</i> (or runtime) types in a single slice! So variance has no use in both languages because no concrete types are eligible for variance anyway.<p>I think the conclusion got weird because the term "subtyping" is being misused. Subtyping, in the broadest sense, is just a non-trivial type relation. Many languages thus have a <i>multiple</i> notion of subtyping, often (almost) identical to each other but sometimes not. Go in particular has a lot of them, and even some relation like "T implements U" is a straightforward record subtyping. So subtyping is indeed a red herring here. Given this, it is no surprise that the non-uniform value representation has the largest influence, and only monomorphization schemes and hetero-to-homogeneous adapters vary in this particular group.<p>[1] <a href="https://github.com/golang/proposal/blob/master/design/generics-implementation-dictionaries-go1.18.md">https://github.com/golang/proposal/blob/master/design/generi...</a><p>[2] <a href="https://rust-lang.github.io/compiler-team/working-groups/polymorphization/" rel="nofollow noreferrer">https://rust-lang.github.io/compiler-team/working-groups/pol...</a>