In case it makes reading easier for people, here's the code with the "A, B, T, U" replaced with what they would expand to. The "that can't work" comes out pretty clear with the equivalent of "Integer-superclass which extends String" which is obvious nonsense.
class Unsound {
static class Constrain<AString, BSuperInteger extends AString> {}
static class Bind<AString> {
<BSuperInteger extends AString>
AString upcast(Constrain<AString, BSuperInteger> constrain, BSuperInteger b) {
return b;
}
}
static <TInteger, UString> UString coerce(TInteger t) {
Constrain<UString, ? super TInteger> constrain = null;
Bind<UString> bind = new Bind<UString>();
return bind.upcast(constrain, t);
}
public static void main(String[] args) {
String zero = Unsound.<Integer, String>coerce(0);
}
}
I left the T, U, A, B as part of the name, so it's easier to map back to the original.I wish people would stop insisting on single-character type variables. They have a purpose - name them meaningfully, like everything else.