// 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 method signatures and return types for the `inout` variance modifier. // SharedOptions=--enable-experiment=variance import "package:expect/expect.dart"; typedef Cov = T Function(); typedef Contra = void Function(T); Cov covFunction = () => 2; Contra contraFunction = (int val) {}; Cov covFunctionNum = () => 2; Contra contraFunctionNum = (num val) {}; class Covariant {} class Contravariant {} class Invariant {} class A { void method1(T x) {} void method2(Cov x) {} Contra method3() { return (T val) { Expect.equals(2, val); }; } T? method4() => null; void method5(Contra x) {} Cov method6() { return () => null; } T method7(T x) => x; Contra method8(Contra x) => x; Cov method9(Cov x) => x; T method10(S x) => x; void method11(Covariant x) {} Covariant? method12() => null; void method13(Contravariant x) {} Contravariant? method14() => null; void method15(Invariant x) {} Invariant? method16() => null; void method17(covariant T x) {} void method18(covariant Contra x) {} void method19(covariant Cov x) {} void method20(covariant Contravariant x) {} void method21(covariant Covariant x) {} void method22>() {} void method23>() {} void method24>() {} void method25>() {} void method26({Contra? a, Cov? b, T? c}) {} void method27({Contravariant? a, Covariant? b}) {} } mixin BMixin { void method1(T x) {} void method2(Cov x) {} Contra method3() { return (T val) { Expect.equals(2, val); }; } T? method4() => null; void method5(Contra x) {} Cov method6() { return () => null; } T method7(T x) => x; Contra method8(Contra x) => x; Cov method9(Cov x) => x; T method10(S x) => x; void method11(Covariant x) {} Covariant? method12() => null; void method13(Contravariant x) {} Contravariant? method14() => null; void method15(Invariant x) {} Invariant? method16() => null; void method17(covariant T x) {} void method18(covariant Contra x) {} void method19(covariant Cov x) {} void method20(covariant Contravariant x) {} void method21(covariant Covariant x) {} void method22>() {} void method23>() {} void method24>() {} void method25>() {} void method26({Contra? a, Cov? b, T? c}) {} void method27({Contravariant? a, Covariant? b}) {} } class B with BMixin {} class C { void method1(Contra> x) {} void method2(Cov> x) {} A method3() { return A(); } } class D { T? method() => null; void method2(T x) {} void method3(covariant T x) {} } class E extends D { @override T? method() => null; @override void method2(T x) {} @override void method3(covariant T x) {} } abstract class F { int method(T x); } class G { final void Function(T) f; G(this.f); int method(T x) { f(x); return -1; } } class H extends G implements F { H(void Function(T) f) : super(f); } void testClass() { A a = new A(); a.method1(2); a.method2(() => 2); Expect.type>(a.method3()); Contra method3Function = a.method3(); method3Function(2); Expect.isNull(a.method4()); a.method5((int val) {}); Expect.type>(a.method6()); Cov method6Function = a.method6(); Expect.isNull(method6Function()); Expect.equals(3, a.method7(3)); Expect.type>(a.method8(contraFunction)); Expect.equals(contraFunction, a.method8(contraFunction)); Expect.type>(a.method9(covFunction)); Expect.equals(covFunction, a.method9(covFunction)); A aa = new A(); Expect.type(aa.method10(3)); a.method11(Covariant()); Expect.isNull(a.method12()); a.method13(Contravariant()); Expect.isNull(a.method14()); a.method15(Invariant()); Expect.isNull(a.method16()); a.method17(3); a.method18(contraFunction); a.method19(covFunction); a.method20(Contravariant()); a.method21(Covariant()); a.method22>(); a.method23>(); a.method24>(); a.method25>(); a.method26(); a.method27(); } void testMixin() { B b = new B(); b.method1(2); b.method2(() => 2); Expect.type>(b.method3()); Contra method3Function = b.method3(); method3Function(2); Expect.isNull(b.method4()); b.method5((num val) {}); Expect.type>(b.method6()); Cov method6Function = b.method6(); Expect.isNull(method6Function()); Expect.equals(3, b.method7(3)); Expect.type>(b.method8(contraFunctionNum)); Expect.equals(contraFunctionNum, b.method8(contraFunctionNum)); Expect.type>(b.method9(covFunctionNum)); Expect.equals(covFunctionNum, b.method9(covFunctionNum)); Expect.type(b.method10(3)); b.method11(Covariant()); Expect.isNull(b.method12()); b.method13(Contravariant()); Expect.isNull(b.method14()); b.method15(Invariant()); Expect.isNull(b.method16()); b.method17(3); b.method18(contraFunctionNum); b.method19(covFunctionNum); b.method20(Contravariant()); b.method21(Covariant()); b.method22>(); b.method23>(); b.method24>(); b.method25>(); b.method26(); b.method27(); } void testClassInMethods() { C c = new C(); c.method1((A x) {}); c.method2(() => throw "uncalled"); Expect.type>(c.method3()); } void testOverrideLegacyMethods() { E e = new E(); Expect.isNull(e.method()); e.method2(3); e.method3(3); D d = e; Expect.throws(() => d.method2("test")); Expect.throws(() => d.method3("test")); F f = new H((String s) {}); Expect.throws(() => f.method(3)); // Tests reified type is the type expected for F and not G. Expect.type(f.method); Expect.type(new H((String s){}).method); } main() { testClass(); testMixin(); testClassInMethods(); testOverrideLegacyMethods(); }