More golang Stockholm syndrome. These arguments are always weird to me. Go has plenty of complex features that go developers don't seem to think cause too much cognitive burden (automatic gc, structural subtyping, etc.). Why is it that relatively simple and ubiquitous language features like exceptions and generics are just way too much and cause an unacceptable amount of complexity? I just don't buy it.

Turn the argument around. Are there any Java, C++, etc. developers arguing for the removal of these features from their languages? Are there people who say that even though these languages have generics you shouldn't touch them because they're bad? Do any devs with option/maybe types really want to go back to unsafe code that can fail if you forget to check for nil/null? Show me someone who hasn't drunk the go kool-aid who still makes these sorts of arguments and I might actually start listening.

> Are there any Java, C++, etc. developers arguing for the removal of these features from their languages?

I will. Generics in Java are a net loss in my opinion. They provide marginal static safety, no additional dynamic safety, no performance benefits, and lead to substantially more complex APIs. I'd have been happier if they were never added. I would prefer a Go-like type-assertion construct or an analogous "occurrence typing" feature.

C#, on the other hand, has a sensible generics implementation that provides meaningful utility thanks to value types. However, I am not ashamed to admit that, in the absence of value types, I'll resort to Whatever plus some casts without a second thought if I find myself doing even the slightest bit of work to satisfy the compiler.

With the exception of value types, there is virtually no difference between Java and C# in terms of parametric polymorphism. Liking one and finding the other a net loss is a bit mystifying.

Besides, the introduction of generics has added a tremendous amount of safety to what used to be typecast littered Java code pre 1.5.

How is it mystifying? You said "besides the one difference you cited, they are not different". I explicitly listed that difference as being the thing that I feel justifies the feature's existence!

> the introduction of generics has added a tremendous amount of safety

It's added marginal _static_ safety. It added no dynamic safety. Static safety is welcome, but frequently not worth the lengths people go to achieve it. Hence my comment about instantiating generic types with Object in the event that the cost outweighs the safety.

> to what used to be typecast littered Java code pre 1.5

Occurrence typing would dramatically minimize the syntactic overhead to casting. There have been research variations of Java that accomplished this: instanceof checks insert implicit casts on branches where the instanceof check is true. Similar extensions have been explored for collections to further omit the instanceof checks without requiring explicit type parameterization. For example, if a collection is only written to privately, you can infer casts from what types are inserted in to the collection. This can achieve the same safety without massive complexity increases to sub-typing, static dispatch, reflection, type signatures, etc.

> There have been research variations of Java that accomplished this: instanceof checks insert implicit casts on branches where the instanceof check is true.

By the way, Go already has this. If you have a variable, say `foo`, with a generic type, say `interface{}`, you can say

  switch foo := foo.(type) {
    case MyFirstConcreteType:
      //foo is a MyFirstConcreteType instance here
    case MySecondConcreteType:
      //foo is a MySecondConcreteType instance here
    default:
      //foo is still the generic type here
  }
See https://golang.org/doc/effective_go.html#type_switch for details.

Yup! Type assertions work this way too. It's a much nicer design than traditional casts.

Check this out. With this tool, the type switch gets you exhaustiveness checks for hokey package-private sum-types in Go :)

https://github.com/BurntSushi/go-sumtype