blob: 0b0e0ff83c0e8e05f613686c76278839ff23897e [file] [log] [blame]
// 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 `out` variance modifier.
// SharedOptions=--enable-experiment=variance
import "package:expect/expect.dart";
typedef Cov<T> = T Function();
typedef Contra<T> = void Function(T);
class A<out T> {
// TODO (kallentu): Come NNBD, change `T` to `T?`
T method1() => null;
void method2(Contra<T> x) {}
Cov<T> method3() {
return () => null;
}
void method4(Contra<Cov<T>> x) {}
void method5(Cov<Contra<T>> x) {}
Contra<Contra<T>> method6() {
return (Contra<T> x) {
Expect.type<Contra<T>>(x);
};
}
Cov<Cov<T>> method7() {
return () {
return () => null;
};
}
}
mixin BMixin<out T> {
// TODO (kallentu): Come NNBD, change `T` to `T?`
T method1() => null;
void method2(Contra<T> x) {}
Cov<T> method3() {
return () => null;
}
void method4(Contra<Cov<T>> x) {}
void method5(Cov<Contra<T>> x) {}
Contra<Contra<T>> method6() {
return (Contra<T> x) {
Expect.type<Contra<T>>(x);
};
}
Cov<Cov<T>> method7() {
return () {
return () => null;
};
}
}
class B with BMixin<int> {}
class C<out T> {
void method1(Contra<A<T>> x) {}
A<T> method2() {
return A<T>();
}
}
void testClass() {
A<int> a = new A();
Expect.isNull(a.method1());
a.method2((int x) {
Expect.equals(2, x);
});
Expect.type<Cov<int>>(a.method3());
Cov<int> method3Function = a.method3();
Expect.isNull(method3Function());
a.method4((Cov<int> x) {});
a.method5(() {
return (int x) {};
});
Expect.type<Contra<Contra<int>>>(a.method6());
Contra<Contra<int>> method6Function = a.method6();
method6Function((int x) {});
Expect.type<Cov<Cov<int>>>(a.method7());
Cov<Cov<int>> method7Function = a.method7();
Expect.type<Cov<int>>(method7Function());
Cov<int> method7NestedFunction = method7Function();
Expect.isNull(method7NestedFunction());
}
void testMixin() {
B b = new B();
Expect.isNull(b.method1());
b.method2((int x) {
Expect.equals(2, x);
});
Expect.type<Cov<int>>(b.method3());
Cov<int> method3Function = b.method3();
Expect.isNull(method3Function());
b.method4((Cov<int> x) {});
b.method5(() {
return (int x) {};
});
Expect.type<Contra<Contra<int>>>(b.method6());
Contra<Contra<int>> method6Function = b.method6();
method6Function((int x) {});
Expect.type<Cov<Cov<int>>>(b.method7());
Cov<Cov<int>> method7Function = b.method7();
Expect.type<Cov<int>>(method7Function());
Cov<int> method7NestedFunction = method7Function();
Expect.isNull(method7NestedFunction());
}
void testClassInMethods() {
C<int> c = new C();
c.method1((A<int> x) {});
Expect.type<A<int>>(c.method2());
}
main() {
testClass();
testMixin();
testClassInMethods();
}