| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // Tests subtyping for the `inout` variance modifier. |
| |
| // SharedOptions=--enable-experiment=variance |
| |
| import 'dart:async'; |
| |
| import "package:expect/expect.dart"; |
| |
| class Invariant<inout T> {} |
| |
| class Upper {} |
| class Middle extends Upper {} |
| class Lower extends Middle {} |
| |
| class A { |
| Invariant<Middle> method1() { |
| return new Invariant<Middle>(); |
| } |
| |
| void method2(Invariant<Middle> x) {} |
| } |
| |
| class B extends A { |
| @override |
| Invariant<Middle> method1() { |
| return new Invariant<Middle>(); |
| } |
| |
| @override |
| void method2(Invariant<Middle> x) {} |
| } |
| |
| class C<out X extends Invariant<Middle>> {} |
| |
| class D { |
| C<Invariant<Middle>> method1() { |
| return C<Invariant<Middle>>(); |
| } |
| } |
| |
| class E { |
| Invariant<dynamic> method1() { |
| return new Invariant<dynamic>(); |
| } |
| |
| void method2(Invariant<Object?> x) {} |
| } |
| |
| class F extends E { |
| @override |
| Invariant<Object?> method1() { |
| return new Invariant<Object?>(); |
| } |
| |
| @override |
| void method2(Invariant<dynamic> x) {} |
| } |
| |
| class G { |
| Invariant<dynamic> method1() { |
| return new Invariant<dynamic>(); |
| } |
| |
| void method2(Invariant<FutureOr<dynamic>> x) {} |
| } |
| |
| class H extends G { |
| @override |
| Invariant<FutureOr<dynamic>> method1() { |
| return new Invariant<FutureOr<dynamic>>(); |
| } |
| |
| @override |
| void method2(Invariant<dynamic> x) {} |
| } |
| |
| class I { |
| Invariant<FutureOr<Never>> method1() { |
| return new Invariant<FutureOr<Never>>(); |
| } |
| |
| void method2(Invariant<Future<Never>> x) {} |
| } |
| |
| class J extends I { |
| @override |
| Invariant<Future<Never>> method1() { |
| return new Invariant<Future<Never>>(); |
| } |
| |
| @override |
| void method2(Invariant<FutureOr<Never>> x) {} |
| } |
| |
| void testCall(Iterable<Invariant<Middle>> x) {} |
| |
| main() { |
| A a = new A(); |
| Expect.type<Invariant<Middle>>(a.method1()); |
| Expect.notType<Invariant<Upper>>(a.method1()); |
| Expect.notType<Invariant<Lower>>(a.method1()); |
| a.method2(new Invariant<Middle>()); |
| |
| B b = new B(); |
| Expect.type<Invariant<Middle>>(b.method1()); |
| Expect.notType<Invariant<Upper>>(b.method1()); |
| Expect.notType<Invariant<Lower>>(b.method1()); |
| b.method2(new Invariant<Middle>()); |
| |
| C<Invariant<Middle>> c = new C<Invariant<Middle>>(); |
| |
| D d = new D(); |
| Expect.type<C<Invariant<Middle>>>(d.method1()); |
| |
| E e = new E(); |
| Expect.type<Invariant<dynamic>>(e.method1()); |
| e.method2(new Invariant<Object?>()); |
| |
| // Invariant<dynamic> <:> Invariant<Object?> |
| F f = new F(); |
| Expect.type<Invariant<Object?>>(f.method1()); |
| Expect.type<Invariant<dynamic>>(f.method1()); |
| f.method2(new Invariant<Object?>()); |
| f.method2(new Invariant<dynamic>()); |
| |
| G g = new G(); |
| Expect.type<Invariant<dynamic>>(g.method1()); |
| g.method2(new Invariant<FutureOr<dynamic>>()); |
| |
| // Invariant<FutureOr<dynamic>> <:> Invariant<dynamic> |
| H h = new H(); |
| Expect.type<Invariant<FutureOr<dynamic>>>(h.method1()); |
| Expect.type<Invariant<dynamic>>(h.method1()); |
| h.method2(new Invariant<FutureOr<dynamic>>()); |
| h.method2(new Invariant<dynamic>()); |
| |
| I i = new I(); |
| Expect.type<Invariant<FutureOr<Never>>>(i.method1()); |
| i.method2(new Invariant<Future<Never>>()); |
| |
| // Invariant<FutureOr<Never>> <:> Invariant<Future<Never>> |
| J j = new J(); |
| Expect.type<Invariant<FutureOr<Never>>>(j.method1()); |
| Expect.type<Invariant<Future<Never>>>(j.method1()); |
| j.method2(new Invariant<FutureOr<Never>>()); |
| j.method2(new Invariant<Future<Never>>()); |
| |
| Iterable<Invariant<Middle>> iterableMiddle = [new Invariant<Middle>()]; |
| List<Invariant<Middle>> listMiddle = [new Invariant<Middle>()]; |
| iterableMiddle = listMiddle; |
| |
| testCall(listMiddle); |
| |
| Expect.subtype<Invariant<Middle>, Invariant<Middle>>(); |
| Expect.notSubtype<Invariant<Lower>, Invariant<Middle>>(); |
| Expect.notSubtype<Invariant<Upper>, Invariant<Middle>>(); |
| |
| Expect.subtype<Invariant<dynamic>, Invariant<Object?>>(); |
| Expect.subtype<Invariant<Object?>, Invariant<dynamic>>(); |
| |
| Expect.subtype<Invariant<FutureOr<dynamic>>, Invariant<dynamic>>(); |
| Expect.subtype<Invariant<dynamic>, Invariant<FutureOr<dynamic>>>(); |
| |
| Expect.subtype<Invariant<FutureOr<Never>>, Invariant<Future<Never>>>(); |
| Expect.subtype<Invariant<Future<Never>>, Invariant<FutureOr<Never>>>(); |
| } |