Index: tests/compiler/dart2js/subtype_test.dart |
diff --git a/tests/compiler/dart2js/subtype_test.dart b/tests/compiler/dart2js/subtype_test.dart |
index 11534ce0742e7fe166232ecac90fe939191cf5f8..c28a6a43ebc3a9634487886ba7075e39ec010da6 100644 |
--- a/tests/compiler/dart2js/subtype_test.dart |
+++ b/tests/compiler/dart2js/subtype_test.dart |
@@ -18,6 +18,7 @@ void main() { |
testTypedefSubtypingOptional(); |
testFunctionSubtypingNamed(); |
testTypedefSubtypingNamed(); |
+ testTypeVariableSubtype(); |
} |
void testInterfaceSubtype() { |
@@ -492,3 +493,220 @@ functionSubtypingNamedHelper(TypeEnvironment env) { |
// 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() { |
+ var env = new TypeEnvironment(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> {} |
+ """); |
+ |
+ void expect(bool value, DartType T, DartType S) { |
+ Expect.equals(value, env.isSubtype(T, S), '$T <: $S'); |
+ } |
+ |
+ 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); |
+} |