class A {} class B extends A { void foo() } /// Unsound (covariant argument types) class C { void m(A a) { } } class D extends C { void m(B b) { b.foo(); } } main: ((C)new D()).m(new A()) class A {} class B extends A { void foo() } /// Unsound (contravariant return types) class C { B m() { return new B(); } } class D extends C { A m() { return new A(); } } main: ((C)new D()).m().foo(); class A {} class B extends A { void foo() } /// Unsound (depth subtyping on mutable fields) class C { A f; } class D extends C { B f; } main: { D d = new D(); ((C)d).f = new A(); d.f.foo(); } class A {} class B extends A { void foo() } /// Unsound (depth subtyping on mutable fields) class C { B f; } class D extends C { A f; } main: { D d = new D(); d.f = new A(); ((C)d).f.foo(); }