| // Copyright (c) 2013, 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. |
| |
| library subtype_test; |
| |
| import 'package:expect/expect.dart'; |
| import "package:async_helper/async_helper.dart"; |
| import 'type_test_helper.dart'; |
| import '../../../sdk/lib/_internal/compiler/implementation/dart_types.dart'; |
| import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart" |
| show Element, ClassElement; |
| |
| void main() { |
| testInterfaceSubtype(); |
| testCallableSubtype(); |
| testFunctionSubtyping(); |
| testTypedefSubtyping(); |
| testFunctionSubtypingOptional(); |
| testTypedefSubtypingOptional(); |
| testFunctionSubtypingNamed(); |
| testTypedefSubtypingNamed(); |
| testTypeVariableSubtype(); |
| } |
| |
| void testTypes(TypeEnvironment env, DartType subtype, DartType supertype, |
| bool expectSubtype, bool expectMoreSpecific) { |
| if (expectMoreSpecific == null) expectMoreSpecific = expectSubtype; |
| Expect.equals(expectSubtype, env.isSubtype(subtype, supertype), |
| '$subtype <: $supertype'); |
| Expect.equals(expectMoreSpecific, env.isMoreSpecific(subtype, supertype), |
| '$subtype << $supertype'); |
| } |
| |
| void testElementTypes(TypeEnvironment env, String subname, String supername, |
| bool expectSubtype, bool expectMoreSpecific) { |
| DartType subtype = env.getElementType(subname); |
| DartType supertype = env.getElementType(supername); |
| testTypes(env, subtype, supertype, expectSubtype, expectMoreSpecific); |
| } |
| |
| |
| void testInterfaceSubtype() { |
| asyncTest(() => TypeEnvironment.create(r""" |
| class A<T> {} |
| class B<T1, T2> extends A<T1> {} |
| // TODO(johnniwinther): Inheritance with different type arguments is |
| // currently not supported by the implementation. |
| class C<T1, T2> extends B<T2, T1> /*implements A<A<T1>>*/ {} |
| """).then((env) { |
| |
| void expect(bool expectSubtype, DartType T, DartType S, |
| {bool expectMoreSpecific}) { |
| testTypes(env, T, S, expectSubtype, expectMoreSpecific); |
| } |
| |
| ClassElement A = env.getElement('A'); |
| ClassElement B = env.getElement('B'); |
| ClassElement C = env.getElement('C'); |
| DartType Object_ = env['Object']; |
| DartType num_ = env['num']; |
| DartType int_ = env['int']; |
| DartType String_ = env['String']; |
| DartType dynamic_ = env['dynamic']; |
| |
| expect(true, Object_, Object_); |
| expect(true, num_, Object_); |
| expect(true, int_, Object_); |
| expect(true, String_, Object_); |
| expect(true, dynamic_, Object_, expectMoreSpecific: false); |
| |
| expect(false, Object_, num_); |
| expect(true, num_, num_); |
| expect(true, int_, num_); |
| expect(false, String_, num_); |
| expect(true, dynamic_, num_, expectMoreSpecific: false); |
| |
| expect(false, Object_, int_); |
| expect(false, num_, int_); |
| expect(true, int_, int_); |
| expect(false, String_, int_); |
| expect(true, dynamic_, int_, expectMoreSpecific: false); |
| |
| expect(false, Object_, String_); |
| expect(false, num_, String_); |
| expect(false, int_, String_); |
| expect(true, String_, String_); |
| expect(true, dynamic_, String_, expectMoreSpecific: false); |
| |
| expect(true, Object_, dynamic_); |
| expect(true, num_, dynamic_); |
| expect(true, int_, dynamic_); |
| expect(true, String_, dynamic_); |
| expect(true, dynamic_, dynamic_); |
| |
| DartType A_Object = instantiate(A, [Object_]); |
| DartType A_num = instantiate(A, [num_]); |
| DartType A_int = instantiate(A, [int_]); |
| DartType A_String = instantiate(A, [String_]); |
| DartType A_dynamic = instantiate(A, [dynamic_]); |
| |
| expect(true, A_Object, Object_); |
| expect(false, A_Object, num_); |
| expect(false, A_Object, int_); |
| expect(false, A_Object, String_); |
| expect(true, A_Object, dynamic_); |
| |
| expect(true, A_Object, A_Object); |
| expect(true, A_num, A_Object); |
| expect(true, A_int, A_Object); |
| expect(true, A_String, A_Object); |
| expect(true, A_dynamic, A_Object, expectMoreSpecific: false); |
| |
| expect(false, A_Object, A_num); |
| expect(true, A_num, A_num); |
| expect(true, A_int, A_num); |
| expect(false, A_String, A_num); |
| expect(true, A_dynamic, A_num, expectMoreSpecific: false); |
| |
| expect(false, A_Object, A_int); |
| expect(false, A_num, A_int); |
| expect(true, A_int, A_int); |
| expect(false, A_String, A_int); |
| expect(true, A_dynamic, A_int, expectMoreSpecific: false); |
| |
| expect(false, A_Object, A_String); |
| expect(false, A_num, A_String); |
| expect(false, A_int, A_String); |
| expect(true, A_String, A_String); |
| expect(true, A_dynamic, A_String, expectMoreSpecific: false); |
| |
| expect(true, A_Object, A_dynamic); |
| expect(true, A_num, A_dynamic); |
| expect(true, A_int, A_dynamic); |
| expect(true, A_String, A_dynamic); |
| expect(true, A_dynamic, A_dynamic); |
| |
| DartType B_Object_Object = instantiate(B, [Object_, Object_]); |
| DartType B_num_num = instantiate(B, [num_, num_]); |
| DartType B_int_num = instantiate(B, [int_, num_]); |
| DartType B_dynamic_dynamic = instantiate(B, [dynamic_, dynamic_]); |
| DartType B_String_dynamic = instantiate(B, [String_, dynamic_]); |
| |
| expect(true, B_Object_Object, Object_); |
| expect(true, B_Object_Object, A_Object); |
| expect(false, B_Object_Object, A_num); |
| expect(false, B_Object_Object, A_int); |
| expect(false, B_Object_Object, A_String); |
| expect(true, B_Object_Object, A_dynamic); |
| |
| expect(true, B_num_num, Object_); |
| expect(true, B_num_num, A_Object); |
| expect(true, B_num_num, A_num); |
| expect(false, B_num_num, A_int); |
| expect(false, B_num_num, A_String); |
| expect(true, B_num_num, A_dynamic); |
| |
| expect(true, B_int_num, Object_); |
| expect(true, B_int_num, A_Object); |
| expect(true, B_int_num, A_num); |
| expect(true, B_int_num, A_int); |
| expect(false, B_int_num, A_String); |
| expect(true, B_int_num, A_dynamic); |
| |
| expect(true, B_dynamic_dynamic, Object_); |
| expect(true, B_dynamic_dynamic, A_Object, expectMoreSpecific: false); |
| expect(true, B_dynamic_dynamic, A_num, expectMoreSpecific: false); |
| expect(true, B_dynamic_dynamic, A_int, expectMoreSpecific: false); |
| expect(true, B_dynamic_dynamic, A_String, expectMoreSpecific: false); |
| expect(true, B_dynamic_dynamic, A_dynamic); |
| |
| expect(true, B_String_dynamic, Object_); |
| expect(true, B_String_dynamic, A_Object); |
| expect(false, B_String_dynamic, A_num); |
| expect(false, B_String_dynamic, A_int); |
| expect(true, B_String_dynamic, A_String); |
| expect(true, B_String_dynamic, A_dynamic); |
| |
| expect(true, B_Object_Object, B_Object_Object); |
| expect(true, B_num_num, B_Object_Object); |
| expect(true, B_int_num, B_Object_Object); |
| expect(true, B_dynamic_dynamic, B_Object_Object, expectMoreSpecific: false); |
| expect(true, B_String_dynamic, B_Object_Object, expectMoreSpecific: false); |
| |
| expect(false, B_Object_Object, B_num_num); |
| expect(true, B_num_num, B_num_num); |
| expect(true, B_int_num, B_num_num); |
| expect(true, B_dynamic_dynamic, B_num_num, expectMoreSpecific: false); |
| expect(false, B_String_dynamic, B_num_num); |
| |
| expect(false, B_Object_Object, B_int_num); |
| expect(false, B_num_num, B_int_num); |
| expect(true, B_int_num, B_int_num); |
| expect(true, B_dynamic_dynamic, B_int_num, expectMoreSpecific: false); |
| expect(false, B_String_dynamic, B_int_num); |
| |
| expect(true, B_Object_Object, B_dynamic_dynamic); |
| expect(true, B_num_num, B_dynamic_dynamic); |
| expect(true, B_int_num, B_dynamic_dynamic); |
| expect(true, B_dynamic_dynamic, B_dynamic_dynamic); |
| expect(true, B_String_dynamic, B_dynamic_dynamic); |
| |
| expect(false, B_Object_Object, B_String_dynamic); |
| expect(false, B_num_num, B_String_dynamic); |
| expect(false, B_int_num, B_String_dynamic); |
| expect(true, B_dynamic_dynamic, B_String_dynamic, |
| expectMoreSpecific: false); |
| expect(true, B_String_dynamic, B_String_dynamic); |
| |
| DartType C_Object_Object = instantiate(C, [Object_, Object_]); |
| DartType C_num_num = instantiate(C, [num_, num_]); |
| DartType C_int_String = instantiate(C, [int_, String_]); |
| DartType C_dynamic_dynamic = instantiate(C, [dynamic_, dynamic_]); |
| |
| expect(true, C_Object_Object, B_Object_Object); |
| expect(false, C_Object_Object, B_num_num); |
| expect(false, C_Object_Object, B_int_num); |
| expect(true, C_Object_Object, B_dynamic_dynamic); |
| expect(false, C_Object_Object, B_String_dynamic); |
| |
| expect(true, C_num_num, B_Object_Object); |
| expect(true, C_num_num, B_num_num); |
| expect(false, C_num_num, B_int_num); |
| expect(true, C_num_num, B_dynamic_dynamic); |
| expect(false, C_num_num, B_String_dynamic); |
| |
| expect(true, C_int_String, B_Object_Object); |
| expect(false, C_int_String, B_num_num); |
| expect(false, C_int_String, B_int_num); |
| expect(true, C_int_String, B_dynamic_dynamic); |
| expect(true, C_int_String, B_String_dynamic); |
| |
| expect(true, C_dynamic_dynamic, B_Object_Object, expectMoreSpecific: false); |
| expect(true, C_dynamic_dynamic, B_num_num, expectMoreSpecific: false); |
| expect(true, C_dynamic_dynamic, B_int_num, expectMoreSpecific: false); |
| expect(true, C_dynamic_dynamic, B_dynamic_dynamic); |
| expect(true, C_dynamic_dynamic, B_String_dynamic, |
| expectMoreSpecific: false); |
| |
| expect(false, C_int_String, A_int); |
| expect(true, C_int_String, A_String); |
| // TODO(johnniwinther): Inheritance with different type arguments is |
| // currently not supported by the implementation. |
| //expect(true, C_int_String, instantiate(A, [A_int])); |
| expect(false, C_int_String, instantiate(A, [A_String])); |
| })); |
| } |
| |
| void testCallableSubtype() { |
| asyncTest(() => TypeEnvironment.create(r""" |
| class U {} |
| class V extends U {} |
| class W extends V {} |
| class A { |
| int call(V v, int i); |
| |
| int m1(U u, int i); |
| int m2(W w, num n); |
| U m3(V v, int i); |
| int m4(V v, U u); |
| void m5(V v, int i); |
| } |
| """).then((env) { |
| void expect(bool expectSubtype, DartType T, DartType S, |
| {bool expectMoreSpecific}) { |
| testTypes(env, T, S, expectSubtype, expectMoreSpecific); |
| } |
| |
| ClassElement classA = env.getElement('A'); |
| DartType A = classA.rawType; |
| DartType function = env['Function']; |
| DartType m1 = env.getMemberType(classA, 'm1'); |
| DartType m2 = env.getMemberType(classA, 'm2'); |
| DartType m3 = env.getMemberType(classA, 'm3'); |
| DartType m4 = env.getMemberType(classA, 'm4'); |
| DartType m5 = env.getMemberType(classA, 'm5'); |
| |
| expect(true, A, function, expectMoreSpecific: false); |
| expect(true, A, m1, expectMoreSpecific: false); |
| expect(true, A, m2, expectMoreSpecific: false); |
| expect(false, A, m3); |
| expect(false, A, m4); |
| expect(true, A, m5, expectMoreSpecific: false); |
| })); |
| } |
| |
| testFunctionSubtyping() { |
| asyncTest(() => TypeEnvironment.create(r""" |
| _() => null; |
| void void_() {} |
| void void_2() {} |
| int int_() => 0; |
| int int_2() => 0; |
| Object Object_() => null; |
| double double_() => 0.0; |
| void void__int(int i) {} |
| int int__int(int i) => 0; |
| int int__int2(int i) => 0; |
| int int__Object(Object o) => 0; |
| Object Object__int(int i) => null; |
| int int__double(double d) => 0; |
| int int__int_int(int i1, int i2) => 0; |
| void inline_void_(void f()) {} |
| void inline_void__int(void f(int i)) {} |
| """).then(functionSubtypingHelper)); |
| } |
| |
| testTypedefSubtyping() { |
| asyncTest(() => TypeEnvironment.create(r""" |
| typedef _(); |
| typedef void void_(); |
| typedef void void_2(); |
| typedef int int_(); |
| typedef int int_2(); |
| typedef Object Object_(); |
| typedef double double_(); |
| typedef void void__int(int i); |
| typedef int int__int(int i); |
| typedef int int__int2(int i); |
| typedef int int__Object(Object o); |
| typedef Object Object__int(int i); |
| typedef int int__double(double d); |
| typedef int int__int_int(int i1, int i2); |
| typedef void inline_void_(void f()); |
| typedef void inline_void__int(void f(int i)); |
| """).then(functionSubtypingHelper)); |
| } |
| |
| functionSubtypingHelper(TypeEnvironment env) { |
| void expect(bool expectSubtype, String sub, String sup, |
| {bool expectMoreSpecific}) { |
| testElementTypes(env, sub, sup, expectSubtype, expectMoreSpecific); |
| } |
| |
| // () -> int <: Function |
| expect(true, 'int_', 'Function'); |
| // Function <: () -> int |
| expect(false, 'Function', 'int_'); |
| |
| // () -> dynamic <: () -> dynamic |
| expect(true, '_', '_'); |
| // () -> dynamic <: () -> void |
| expect(true, '_', 'void_'); |
| // () -> void <: () -> dynamic |
| expect(true, 'void_', '_', expectMoreSpecific: false); |
| |
| // () -> int <: () -> void |
| expect(true, 'int_', 'void_'); |
| // () -> void <: () -> int |
| expect(false, 'void_', 'int_'); |
| // () -> void <: () -> void |
| expect(true, 'void_', 'void_2'); |
| // () -> int <: () -> int |
| expect(true, 'int_', 'int_2'); |
| // () -> int <: () -> Object |
| expect(true, 'int_', 'Object_'); |
| // () -> int <: () -> double |
| expect(false, 'int_', 'double_'); |
| // () -> int <: (int) -> void |
| expect(false, 'int_', 'void__int'); |
| // () -> void <: (int) -> int |
| expect(false, 'void_', 'int__int'); |
| // () -> void <: (int) -> void |
| expect(false, 'void_', 'void__int'); |
| // (int) -> int <: (int) -> int |
| expect(true, 'int__int', 'int__int2'); |
| // (Object) -> int <: (int) -> Object |
| expect(true, 'int__Object', 'Object__int', expectMoreSpecific: false); |
| // (int) -> int <: (double) -> int |
| expect(false, 'int__int', 'int__double'); |
| // () -> int <: (int) -> int |
| expect(false, 'int_', 'int__int'); |
| // (int) -> int <: (int,int) -> int |
| expect(false, 'int__int', 'int__int_int'); |
| // (int,int) -> int <: (int) -> int |
| expect(false, 'int__int_int', 'int__int'); |
| // (()->void) -> void <: ((int)->void) -> void |
| expect(false, 'inline_void_', 'inline_void__int'); |
| // ((int)->void) -> void <: (()->void) -> void |
| expect(false, 'inline_void__int', 'inline_void_'); |
| } |
| |
| testFunctionSubtypingOptional() { |
| asyncTest(() => TypeEnvironment.create(r""" |
| void void_() {} |
| void void__int(int i) {} |
| void void___int([int i]) {} |
| void void___int2([int i]) {} |
| void void___Object([Object o]) {} |
| void void__int__int(int i1, [int i2]) {} |
| void void__int__int2(int i1, [int i2]) {} |
| void void__int__int_int(int i1, [int i2, int i3]); |
| void void___double(double d) {} |
| void void___int_int([int i1, int i2]) {} |
| void void___int_int_int([int i1, int i2, int i3]); |
| void void___Object_int([Object o, int i]) {} |
| """).then(functionSubtypingOptionalHelper)); |
| } |
| |
| testTypedefSubtypingOptional() { |
| asyncTest(() => TypeEnvironment.create(r""" |
| typedef void void_(); |
| typedef void void__int(int i); |
| typedef void void___int([int i]); |
| typedef void void___int2([int i]); |
| typedef void void___Object([Object o]); |
| typedef void void__int__int(int i1, [int i2]); |
| typedef void void__int__int2(int i1, [int i2]); |
| typedef void void__int__int_int(int i1, [int i2, int i3]); |
| typedef void void___double(double d); |
| typedef void void___int_int([int i1, int i2]); |
| typedef void void___int_int_int([int i1, int i2, int i3]); |
| typedef void void___Object_int([Object o, int i]); |
| """).then(functionSubtypingOptionalHelper)); |
| } |
| |
| functionSubtypingOptionalHelper(TypeEnvironment env) { |
| void expect(bool expectSubtype, String sub, String sup, |
| {bool expectMoreSpecific}) { |
| testElementTypes(env, sub, sup, expectSubtype, expectMoreSpecific); |
| } |
| |
| // Test ([int])->void <: ()->void. |
| expect(true, 'void___int', 'void_'); |
| // Test ([int])->void <: (int)->void. |
| expect(true, 'void___int', 'void__int'); |
| // Test (int)->void <: ([int])->void. |
| expect(false, 'void__int', 'void___int'); |
| // Test ([int])->void <: ([int])->void. |
| expect(true, 'void___int', 'void___int2'); |
| // Test ([Object])->void <: ([int])->void. |
| expect(true, 'void___Object', 'void___int', expectMoreSpecific: false); |
| // Test ([int])->void <: ([Object])->void. |
| expect(true, 'void___int', 'void___Object'); |
| // Test (int,[int])->void <: (int)->void. |
| expect(true, 'void__int__int', 'void__int'); |
| // Test (int,[int])->void <: (int,[int])->void. |
| expect(true, 'void__int__int', 'void__int__int2'); |
| // Test (int)->void <: ([int])->void. |
| expect(false, 'void__int', 'void___int'); |
| // Test ([int,int])->void <: (int)->void. |
| expect(true, 'void___int_int', 'void__int'); |
| // Test ([int,int])->void <: (int,[int])->void. |
| expect(true, 'void___int_int', 'void__int__int'); |
| // Test ([int,int])->void <: (int,[int,int])->void. |
| expect(false, 'void___int_int', 'void__int__int_int'); |
| // Test ([int,int,int])->void <: (int,[int,int])->void. |
| expect(true, 'void___int_int_int', 'void__int__int_int'); |
| // Test ([int])->void <: ([double])->void. |
| expect(false, 'void___int', 'void___double'); |
| // Test ([int])->void <: ([int,int])->void. |
| expect(false, 'void___int', 'void___int_int'); |
| // Test ([int,int])->void <: ([int])->void. |
| expect(true, 'void___int_int', 'void___int'); |
| // Test ([Object,int])->void <: ([int])->void. |
| expect(true, 'void___Object_int', 'void___int', expectMoreSpecific: false); |
| } |
| |
| testFunctionSubtypingNamed() { |
| asyncTest(() => TypeEnvironment.create(r""" |
| void void_() {} |
| void void__int(int i) {} |
| void void___a_int({int a}) {} |
| void void___a_int2({int a}) {} |
| void void___b_int({int b}) {} |
| void void___a_Object({Object a}) {} |
| void void__int__a_int(int i1, {int a}) {} |
| void void__int__a_int2(int i1, {int a}) {} |
| void void___a_double({double a}) {} |
| void void___a_int_b_int({int a, int b}) {} |
| void void___a_int_b_int_c_int({int a, int b, int c}) {} |
| void void___a_int_c_int({int a, int c}) {} |
| void void___b_int_c_int({int b, int c}) {} |
| void void___c_int({int c}) {} |
| """).then(functionSubtypingNamedHelper)); |
| } |
| |
| testTypedefSubtypingNamed() { |
| asyncTest(() => TypeEnvironment.create(r""" |
| typedef void void_(); |
| typedef void void__int(int i); |
| typedef void void___a_int({int a}); |
| typedef void void___a_int2({int a}); |
| typedef void void___b_int({int b}); |
| typedef void void___a_Object({Object a}); |
| typedef void void__int__a_int(int i1, {int a}); |
| typedef void void__int__a_int2(int i1, {int a}); |
| typedef void void___a_double({double a}); |
| typedef void void___a_int_b_int({int a, int b}); |
| typedef void void___a_int_b_int_c_int({int a, int b, int c}); |
| typedef void void___a_int_c_int({int a, int c}); |
| typedef void void___b_int_c_int({int b, int c}); |
| typedef void void___c_int({int c}); |
| """).then(functionSubtypingNamedHelper)); |
| } |
| |
| functionSubtypingNamedHelper(TypeEnvironment env) { |
| expect(bool expectSubtype, String sub, String sup, |
| {bool expectMoreSpecific}) { |
| testElementTypes(env, sub, sup, expectSubtype, expectMoreSpecific); |
| } |
| |
| // Test ({int a})->void <: ()->void. |
| expect(true, 'void___a_int', 'void_'); |
| // Test ({int a})->void <: (int)->void. |
| expect(false, 'void___a_int', 'void__int'); |
| // Test (int)->void <: ({int a})->void. |
| expect(false, 'void__int', 'void___a_int'); |
| // Test ({int a})->void <: ({int a})->void. |
| expect(true, 'void___a_int', 'void___a_int2'); |
| // Test ({int a})->void <: ({int b})->void. |
| expect(false, 'void___a_int', 'void___b_int'); |
| // Test ({Object a})->void <: ({int a})->void. |
| expect(true, 'void___a_Object', 'void___a_int', expectMoreSpecific: false); |
| // Test ({int a})->void <: ({Object a})->void. |
| expect(true, 'void___a_int', 'void___a_Object'); |
| // Test (int,{int a})->void <: (int,{int a})->void. |
| expect(true, 'void__int__a_int', 'void__int__a_int2'); |
| // Test ({int a})->void <: ({double a})->void. |
| expect(false, 'void___a_int', 'void___a_double'); |
| // Test ({int a})->void <: ({int a,int b})->void. |
| expect(false, 'void___a_int', 'void___a_int_b_int'); |
| // Test ({int a,int b})->void <: ({int a})->void. |
| expect(true, 'void___a_int_b_int', 'void___a_int'); |
| // Test ({int a,int b,int c})->void <: ({int a,int c})->void. |
| expect(true, 'void___a_int_b_int_c_int', 'void___a_int_c_int'); |
| // Test ({int a,int b,int c})->void <: ({int b,int c})->void. |
| expect(true, 'void___a_int_b_int_c_int', 'void___b_int_c_int'); |
| // Test ({int a,int b,int c})->void <: ({int c})->void. |
| expect(true, 'void___a_int_b_int_c_int', 'void___c_int'); |
| } |
| |
| void testTypeVariableSubtype() { |
| asyncTest(() => TypeEnvironment.create(r""" |
| class A<T> {} |
| class B<T extends Object> {} |
| class C<T extends num> {} |
| class D<T extends int> {} |
| class E<T extends S, S extends num> {} |
| class F<T extends num, S extends T> {} |
| class G<T extends T> {} |
| class H<T extends S, S extends T> {} |
| class I<T extends S, S extends U, U extends T> {} |
| class J<T extends S, S extends U, U extends S> {} |
| """).then((env) { |
| void expect(bool expectSubtype, DartType T, DartType S, |
| {bool expectMoreSpecific}) { |
| testTypes(env, T, S, expectSubtype, expectMoreSpecific); |
| } |
| |
| ClassElement A = env.getElement('A'); |
| TypeVariableType A_T = A.thisType.typeArguments.head; |
| ClassElement B = env.getElement('B'); |
| TypeVariableType B_T = B.thisType.typeArguments.head; |
| ClassElement C = env.getElement('C'); |
| TypeVariableType C_T = C.thisType.typeArguments.head; |
| ClassElement D = env.getElement('D'); |
| TypeVariableType D_T = D.thisType.typeArguments.head; |
| ClassElement E = env.getElement('E'); |
| TypeVariableType E_T = E.thisType.typeArguments.head; |
| TypeVariableType E_S = E.thisType.typeArguments.tail.head; |
| ClassElement F = env.getElement('F'); |
| TypeVariableType F_T = F.thisType.typeArguments.head; |
| TypeVariableType F_S = F.thisType.typeArguments.tail.head; |
| ClassElement G = env.getElement('G'); |
| TypeVariableType G_T = G.thisType.typeArguments.head; |
| ClassElement H = env.getElement('H'); |
| TypeVariableType H_T = H.thisType.typeArguments.head; |
| TypeVariableType H_S = H.thisType.typeArguments.tail.head; |
| ClassElement I = env.getElement('I'); |
| TypeVariableType I_T = I.thisType.typeArguments.head; |
| TypeVariableType I_S = I.thisType.typeArguments.tail.head; |
| TypeVariableType I_U = I.thisType.typeArguments.tail.tail.head; |
| ClassElement J = env.getElement('J'); |
| TypeVariableType J_T = J.thisType.typeArguments.head; |
| TypeVariableType J_S = J.thisType.typeArguments.tail.head; |
| TypeVariableType J_U = J.thisType.typeArguments.tail.tail.head; |
| |
| DartType Object_ = env['Object']; |
| DartType num_ = env['num']; |
| DartType int_ = env['int']; |
| DartType String_ = env['String']; |
| DartType dynamic_ = env['dynamic']; |
| |
| // class A<T> {} |
| expect(true, A_T, Object_); |
| expect(false, A_T, num_); |
| expect(false, A_T, int_); |
| expect(false, A_T, String_); |
| expect(true, A_T, dynamic_); |
| expect(true, A_T, A_T); |
| expect(false, A_T, B_T); |
| |
| // class B<T extends Object> {} |
| expect(true, B_T, Object_); |
| expect(false, B_T, num_); |
| expect(false, B_T, int_); |
| expect(false, B_T, String_); |
| expect(true, B_T, dynamic_); |
| expect(true, B_T, B_T); |
| expect(false, B_T, A_T); |
| |
| // class C<T extends num> {} |
| expect(true, C_T, Object_); |
| expect(true, C_T, num_); |
| expect(false, C_T, int_); |
| expect(false, C_T, String_); |
| expect(true, C_T, dynamic_); |
| expect(true, C_T, C_T); |
| expect(false, C_T, A_T); |
| |
| // class D<T extends int> {} |
| expect(true, D_T, Object_); |
| expect(true, D_T, num_); |
| expect(true, D_T, int_); |
| expect(false, D_T, String_); |
| expect(true, D_T, dynamic_); |
| expect(true, D_T, D_T); |
| expect(false, D_T, A_T); |
| |
| // class E<T extends S, S extends num> {} |
| expect(true, E_T, Object_); |
| expect(true, E_T, num_); |
| expect(false, E_T, int_); |
| expect(false, E_T, String_); |
| expect(true, E_T, dynamic_); |
| expect(true, E_T, E_T); |
| expect(true, E_T, E_S); |
| expect(false, E_T, A_T); |
| |
| expect(true, E_S, Object_); |
| expect(true, E_S, num_); |
| expect(false, E_S, int_); |
| expect(false, E_S, String_); |
| expect(true, E_S, dynamic_); |
| expect(false, E_S, E_T); |
| expect(true, E_S, E_S); |
| expect(false, E_S, A_T); |
| |
| // class F<T extends num, S extends T> {} |
| expect(true, F_T, Object_); |
| expect(true, F_T, num_); |
| expect(false, F_T, int_); |
| expect(false, F_T, String_); |
| expect(true, F_T, dynamic_); |
| expect(false, F_T, F_S); |
| expect(true, F_T, F_T); |
| expect(false, F_T, A_T); |
| |
| expect(true, F_S, Object_); |
| expect(true, F_S, num_); |
| expect(false, F_S, int_); |
| expect(false, F_S, String_); |
| expect(true, F_S, dynamic_); |
| expect(true, F_S, F_S); |
| expect(true, F_S, F_T); |
| expect(false, F_S, A_T); |
| |
| // class G<T extends T> {} |
| expect(true, G_T, Object_); |
| expect(false, G_T, num_); |
| expect(false, G_T, int_); |
| expect(false, G_T, String_); |
| expect(true, G_T, dynamic_); |
| expect(true, G_T, G_T); |
| expect(false, G_T, A_T); |
| |
| // class H<T extends S, S extends T> {} |
| expect(true, H_T, Object_); |
| expect(false, H_T, num_); |
| expect(false, H_T, int_); |
| expect(false, H_T, String_); |
| expect(true, H_T, dynamic_); |
| expect(true, H_T, H_T); |
| expect(true, H_T, H_S); |
| expect(false, H_T, A_T); |
| |
| expect(true, H_S, Object_); |
| expect(false, H_S, num_); |
| expect(false, H_S, int_); |
| expect(false, H_S, String_); |
| expect(true, H_S, dynamic_); |
| expect(true, H_S, H_T); |
| expect(true, H_S, H_S); |
| expect(false, H_S, A_T); |
| |
| // class I<T extends S, S extends U, U extends T> {} |
| expect(true, I_T, Object_); |
| expect(false, I_T, num_); |
| expect(false, I_T, int_); |
| expect(false, I_T, String_); |
| expect(true, I_T, dynamic_); |
| expect(true, I_T, I_T); |
| expect(true, I_T, I_S); |
| expect(true, I_T, I_U); |
| expect(false, I_T, A_T); |
| |
| expect(true, I_S, Object_); |
| expect(false, I_S, num_); |
| expect(false, I_S, int_); |
| expect(false, I_S, String_); |
| expect(true, I_S, dynamic_); |
| expect(true, I_S, I_T); |
| expect(true, I_S, I_S); |
| expect(true, I_S, I_U); |
| expect(false, I_S, A_T); |
| |
| expect(true, I_U, Object_); |
| expect(false, I_U, num_); |
| expect(false, I_U, int_); |
| expect(false, I_U, String_); |
| expect(true, I_U, dynamic_); |
| expect(true, I_U, I_T); |
| expect(true, I_U, I_S); |
| expect(true, I_U, I_U); |
| expect(false, I_U, A_T); |
| |
| // class J<T extends S, S extends U, U extends S> {} |
| expect(true, J_T, Object_); |
| expect(false, J_T, num_); |
| expect(false, J_T, int_); |
| expect(false, J_T, String_); |
| expect(true, J_T, dynamic_); |
| expect(true, J_T, J_T); |
| expect(true, J_T, J_S); |
| expect(true, J_T, J_U); |
| expect(false, J_T, A_T); |
| |
| expect(true, J_S, Object_); |
| expect(false, J_S, num_); |
| expect(false, J_S, int_); |
| expect(false, J_S, String_); |
| expect(true, J_S, dynamic_); |
| expect(false, J_S, J_T); |
| expect(true, J_S, J_S); |
| expect(true, J_S, J_U); |
| expect(false, J_S, A_T); |
| |
| expect(true, J_U, Object_); |
| expect(false, J_U, num_); |
| expect(false, J_U, int_); |
| expect(false, J_U, String_); |
| expect(true, J_U, dynamic_); |
| expect(false, J_U, J_T); |
| expect(true, J_U, J_S); |
| expect(true, J_U, J_U); |
| expect(false, J_U, A_T); |
| })); |
| } |