// Counterexample with contravariant this type class C { next: this; // error (see below for exploit): `this` should only appear in // covariant positions } class D extends C { } var d = new D(); (d: C).next = new C; (d.next: D); // sneaky class A { foo(that: X) { } // error: can't hide contravariance using a bound } class B extends A { foo(that: Y) { } // error (see above, catches hidden override) } // covariance checks on this type in invariant positions class Invariant { out_object(): { _: this } { return { _: this }; } in_object(_: { _: this }) { } inout_object: { _: this }; out_array(): Array { return [this]; } in_array(_: Array) { } inout_array: Array; } // covariance checks on this type as type args class Misc { // Set has invariant X out_set(): Set { return new Set().add(this); } in_set(_: Set) { } inout_set: Set; // Promise has covariant X async out_promise(): Promise { return this; } in_promise(_: Promise) { } inout_promise: Promise; // Generator has covariant X, covariant Y, contravariant Z *out_generator(): Generator { yield this; return this; } in_generator(_: Generator) { } inout_generator: Generator; }