| Index: pkg/analyzer/test/generated/type_system_test.dart
|
| diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
|
| index c24297f2860b05a1763d94921daa9076a28485f4..160a4e75e6e94ae317583b9a5f0abe4975a31898 100644
|
| --- a/pkg/analyzer/test/generated/type_system_test.dart
|
| +++ b/pkg/analyzer/test/generated/type_system_test.dart
|
| @@ -10,6 +10,7 @@ import 'package:analyzer/src/generated/element.dart';
|
| import 'package:analyzer/src/generated/resolver.dart';
|
| import 'package:analyzer/src/generated/testing/element_factory.dart';
|
| import 'package:analyzer/src/generated/testing/test_type_provider.dart';
|
| +import 'package:analyzer/src/generated/utilities_dart.dart';
|
| import 'package:unittest/unittest.dart';
|
|
|
| import '../reflective_tests.dart';
|
| @@ -18,6 +19,8 @@ import '../utils.dart';
|
| main() {
|
| initializeTestEnvironment();
|
| runReflectiveTests(TypeSystemTest);
|
| + runReflectiveTests(StrongSubtypingTest);
|
| + runReflectiveTests(StrongAssignabilityTest);
|
| }
|
|
|
| @reflectiveTest
|
| @@ -39,7 +42,7 @@ class TypeSystemTest {
|
|
|
| void setUp() {
|
| typeProvider = new TestTypeProvider();
|
| - typeSystem = new TypeSystemImpl(typeProvider);
|
| + typeSystem = new TypeSystemImpl();
|
| FunctionTypeAliasElementImpl typeAlias =
|
| ElementFactory.functionTypeAliasElement('A');
|
| typeAlias.parameters = [];
|
| @@ -160,14 +163,21 @@ class TypeSystemTest {
|
| DartType typeParam = ElementFactory.typeParameterElement('T').type;
|
| DartType interfaceType = ElementFactory.classElement2('A', []).type;
|
| expect(
|
| - typeSystem.getLeastUpperBound(dynamicType, dynamicType), dynamicType);
|
| - expect(typeSystem.getLeastUpperBound(voidType, voidType), voidType);
|
| - expect(typeSystem.getLeastUpperBound(bottomType, bottomType), bottomType);
|
| - expect(typeSystem.getLeastUpperBound(typeParam, typeParam), typeParam);
|
| - expect(typeSystem.getLeastUpperBound(interfaceType, interfaceType),
|
| + typeSystem.getLeastUpperBound(typeProvider, dynamicType, dynamicType),
|
| + dynamicType);
|
| + expect(typeSystem.getLeastUpperBound(typeProvider, voidType, voidType),
|
| + voidType);
|
| + expect(typeSystem.getLeastUpperBound(typeProvider, bottomType, bottomType),
|
| + bottomType);
|
| + expect(typeSystem.getLeastUpperBound(typeProvider, typeParam, typeParam),
|
| + typeParam);
|
| + expect(
|
| + typeSystem.getLeastUpperBound(
|
| + typeProvider, interfaceType, interfaceType),
|
| interfaceType);
|
| expect(
|
| - typeSystem.getLeastUpperBound(simpleFunctionType, simpleFunctionType),
|
| + typeSystem.getLeastUpperBound(
|
| + typeProvider, simpleFunctionType, simpleFunctionType),
|
| simpleFunctionType);
|
| }
|
|
|
| @@ -329,7 +339,9 @@ class TypeSystemTest {
|
| // List<int>
|
| //
|
| InterfaceType listOfIntType = listType.substitute4(<DartType>[intType]);
|
| - expect(typeSystem.getLeastUpperBound(listOfIntType, listOfIntType),
|
| + expect(
|
| + typeSystem.getLeastUpperBound(
|
| + typeProvider, listOfIntType, listOfIntType),
|
| listOfIntType);
|
| }
|
|
|
| @@ -353,6 +365,565 @@ class TypeSystemTest {
|
|
|
| void _checkLeastUpperBound(
|
| DartType type1, DartType type2, DartType expectedResult) {
|
| - expect(typeSystem.getLeastUpperBound(type1, type2), expectedResult);
|
| + expect(typeSystem.getLeastUpperBound(typeProvider, type1, type2),
|
| + expectedResult);
|
| + }
|
| +}
|
| +
|
| +class TypeBuilder {
|
| + static FunctionType functionType(
|
| + List<DartType> parameters, DartType returnType,
|
| + {List<DartType> optional, Map<String, DartType> named}) {
|
| + return ElementFactory
|
| + .functionElement8(parameters, returnType,
|
| + optional: optional, named: named)
|
| + .type;
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class StrongSubtypingTest {
|
| + TypeProvider typeProvider;
|
| + TypeSystem typeSystem;
|
| +
|
| + DartType get bottomType => typeProvider.bottomType;
|
| + InterfaceType get doubleType => typeProvider.doubleType;
|
| + DartType get dynamicType => typeProvider.dynamicType;
|
| + InterfaceType get functionType => typeProvider.functionType;
|
| + InterfaceType get intType => typeProvider.intType;
|
| + InterfaceType get listType => typeProvider.listType;
|
| + InterfaceType get numType => typeProvider.numType;
|
| + InterfaceType get objectType => typeProvider.objectType;
|
| + InterfaceType get stringType => typeProvider.stringType;
|
| + DartType get voidType => VoidTypeImpl.instance;
|
| +
|
| + void setUp() {
|
| + typeProvider = new TestTypeProvider();
|
| + typeSystem = new StrongTypeSystemImpl();
|
| + }
|
| +
|
| + void test_isSubtypeOf_dynamic_isTop() {
|
| + DartType interfaceType = ElementFactory.classElement2('A', []).type;
|
| + List<DartType> equivalents = <DartType>[dynamicType, objectType];
|
| + List<DartType> subtypes = <DartType>[
|
| + intType,
|
| + doubleType,
|
| + numType,
|
| + stringType,
|
| + functionType,
|
| + interfaceType,
|
| + bottomType
|
| + ];
|
| + _checkGroups(dynamicType, equivalents: equivalents, subtypes: subtypes);
|
| + }
|
| +
|
| + void test_isSubtypeOf_bottom_isBottom() {
|
| + DartType interfaceType = ElementFactory.classElement2('A', []).type;
|
| + List<DartType> equivalents = <DartType>[bottomType];
|
| + List<DartType> supertypes = <DartType>[
|
| + dynamicType,
|
| + objectType,
|
| + intType,
|
| + doubleType,
|
| + numType,
|
| + stringType,
|
| + functionType,
|
| + interfaceType
|
| + ];
|
| + _checkGroups(bottomType, equivalents: equivalents, supertypes: supertypes);
|
| + }
|
| +
|
| + void test_isSubtypeOf_int() {
|
| + List<DartType> equivalents = <DartType>[intType];
|
| + List<DartType> supertypes = <DartType>[numType];
|
| + List<DartType> unrelated = <DartType>[doubleType];
|
| + _checkGroups(intType,
|
| + equivalents: equivalents, supertypes: supertypes, unrelated: unrelated);
|
| + }
|
| +
|
| + void test_isSubtypeOf_double() {
|
| + List<DartType> equivalents = <DartType>[doubleType];
|
| + List<DartType> supertypes = <DartType>[numType];
|
| + List<DartType> unrelated = <DartType>[intType];
|
| + _checkGroups(doubleType,
|
| + equivalents: equivalents, supertypes: supertypes, unrelated: unrelated);
|
| + }
|
| +
|
| + void test_isSubtypeOf_num() {
|
| + List<DartType> equivalents = <DartType>[numType];
|
| + List<DartType> supertypes = <DartType>[];
|
| + List<DartType> unrelated = <DartType>[stringType];
|
| + List<DartType> subtypes = <DartType>[intType, doubleType];
|
| + _checkGroups(numType,
|
| + equivalents: equivalents,
|
| + supertypes: supertypes,
|
| + unrelated: unrelated,
|
| + subtypes: subtypes);
|
| + }
|
| +
|
| + void test_isSubtypeOf_classes() {
|
| + ClassElement classTop = ElementFactory.classElement2("A");
|
| + ClassElement classLeft = ElementFactory.classElement("B", classTop.type);
|
| + ClassElement classRight = ElementFactory.classElement("C", classTop.type);
|
| + ClassElement classBottom = ElementFactory.classElement("D", classLeft.type)
|
| + ..interfaces = <InterfaceType>[classRight.type];
|
| + InterfaceType top = classTop.type;
|
| + InterfaceType left = classLeft.type;
|
| + InterfaceType right = classRight.type;
|
| + InterfaceType bottom = classBottom.type;
|
| +
|
| + _checkLattice(top, left, right, bottom);
|
| + }
|
| +
|
| + void test_isSubtypeOf_simple_function() {
|
| + FunctionType top =
|
| + TypeBuilder.functionType(<DartType>[intType], objectType);
|
| + FunctionType left = TypeBuilder.functionType(<DartType>[intType], intType);
|
| + FunctionType right =
|
| + TypeBuilder.functionType(<DartType>[objectType], objectType);
|
| + FunctionType bottom =
|
| + TypeBuilder.functionType(<DartType>[objectType], intType);
|
| +
|
| + _checkLattice(top, left, right, bottom);
|
| + }
|
| +
|
| + void test_isSubtypeOf_call_method() {
|
| + ClassElementImpl classBottom = ElementFactory.classElement2("Bottom");
|
| + MethodElement methodBottom =
|
| + ElementFactory.methodElement("call", objectType, <DartType>[intType]);
|
| + classBottom.methods = <MethodElement>[methodBottom];
|
| +
|
| + DartType top = TypeBuilder.functionType(<DartType>[intType], objectType);
|
| + InterfaceType bottom = classBottom.type;
|
| +
|
| + _checkIsStrictSubtypeOf(bottom, top);
|
| + }
|
| +
|
| + void test_isSubtypeOf_fuzzy_arrows() {
|
| + FunctionType top =
|
| + TypeBuilder.functionType(<DartType>[dynamicType], objectType);
|
| + FunctionType left =
|
| + TypeBuilder.functionType(<DartType>[objectType], objectType);
|
| + FunctionType right =
|
| + TypeBuilder.functionType(<DartType>[dynamicType], bottomType);
|
| + FunctionType bottom =
|
| + TypeBuilder.functionType(<DartType>[objectType], bottomType);
|
| +
|
| + _checkLattice(top, left, right, bottom);
|
| + }
|
| +
|
| + void test_isSubtypeOf_void_functions() {
|
| + FunctionType top = TypeBuilder.functionType(<DartType>[intType], voidType);
|
| + FunctionType bottom =
|
| + TypeBuilder.functionType(<DartType>[objectType], intType);
|
| +
|
| + _checkIsStrictSubtypeOf(bottom, top);
|
| + }
|
| +
|
| + void test_isSubtypeOf_named_optional() {
|
| + DartType r = TypeBuilder.functionType(<DartType>[intType], intType);
|
| + DartType o = TypeBuilder.functionType(<DartType>[], intType,
|
| + optional: <DartType>[intType]);
|
| + DartType n = TypeBuilder.functionType(<DartType>[], intType,
|
| + named: <String, DartType>{'x': intType});
|
| + DartType rr =
|
| + TypeBuilder.functionType(<DartType>[intType, intType], intType);
|
| + DartType ro = TypeBuilder.functionType(<DartType>[intType], intType,
|
| + optional: <DartType>[intType]);
|
| + DartType rn = TypeBuilder.functionType(<DartType>[intType], intType,
|
| + named: <String, DartType>{'x': intType});
|
| + DartType oo = TypeBuilder.functionType(<DartType>[], intType,
|
| + optional: <DartType>[intType, intType]);
|
| + DartType nn = TypeBuilder.functionType(<DartType>[], intType,
|
| + named: <String, DartType>{'x': intType, 'y': intType});
|
| + DartType nnn = TypeBuilder.functionType(<DartType>[], intType,
|
| + named: <String, DartType>{'x': intType, 'y': intType, 'z': intType});
|
| +
|
| + _checkGroups(r,
|
| + equivalents: [r],
|
| + subtypes: [o, ro, rn, oo],
|
| + unrelated: [n, rr, nn, nnn]);
|
| + _checkGroups(o,
|
| + equivalents: [o], subtypes: [oo], unrelated: [n, rr, ro, rn, nn, nnn]);
|
| + _checkGroups(n,
|
| + equivalents: [n],
|
| + subtypes: [nn, nnn],
|
| + unrelated: [r, o, rr, ro, rn, oo]);
|
| + _checkGroups(rr,
|
| + equivalents: [rr],
|
| + subtypes: [ro, oo],
|
| + unrelated: [r, o, n, rn, nn, nnn]);
|
| + _checkGroups(ro,
|
| + equivalents: [ro], subtypes: [oo], unrelated: [o, n, rn, nn, nnn]);
|
| + _checkGroups(rn,
|
| + equivalents: [rn],
|
| + subtypes: [],
|
| + unrelated: [o, n, rr, ro, oo, nn, nnn]);
|
| + _checkGroups(oo,
|
| + equivalents: [oo], subtypes: [], unrelated: [n, rn, nn, nnn]);
|
| + _checkGroups(nn,
|
| + equivalents: [nn], subtypes: [nnn], unrelated: [r, o, rr, ro, rn, oo]);
|
| + _checkGroups(nnn,
|
| + equivalents: [nnn], subtypes: [], unrelated: [r, o, rr, ro, rn, oo]);
|
| + }
|
| +
|
| + void test_isSubtypeOf_generics() {
|
| + ClassElementImpl LClass = ElementFactory.classElement2('L', ["T"]);
|
| + InterfaceType LType = LClass.type;
|
| + ClassElementImpl MClass = ElementFactory.classElement2('M', ["T"]);
|
| + DartType typeParam = MClass.typeParameters[0].type;
|
| + InterfaceType superType = LType.substitute4(<DartType>[typeParam]);
|
| + MClass.interfaces = <InterfaceType>[superType];
|
| + InterfaceType MType = MClass.type;
|
| +
|
| + InterfaceType top = LType.substitute4(<DartType>[dynamicType]);
|
| + InterfaceType left = MType.substitute4(<DartType>[dynamicType]);
|
| + InterfaceType right = LType.substitute4(<DartType>[intType]);
|
| + InterfaceType bottom = MType.substitute4(<DartType>[intType]);
|
| +
|
| + _checkLattice(top, left, right, bottom);
|
| + }
|
| +
|
| + void _checkLattice(
|
| + DartType top, DartType left, DartType right, DartType bottom) {
|
| + _checkGroups(top,
|
| + equivalents: <DartType>[top],
|
| + subtypes: <DartType>[left, right, bottom]);
|
| + _checkGroups(left,
|
| + equivalents: <DartType>[left],
|
| + subtypes: <DartType>[bottom],
|
| + unrelated: <DartType>[right],
|
| + supertypes: <DartType>[top]);
|
| + _checkGroups(right,
|
| + equivalents: <DartType>[right],
|
| + subtypes: <DartType>[bottom],
|
| + unrelated: <DartType>[left],
|
| + supertypes: <DartType>[top]);
|
| + _checkGroups(bottom,
|
| + equivalents: <DartType>[bottom],
|
| + supertypes: <DartType>[top, left, right]);
|
| + }
|
| +
|
| + void _checkGroups(DartType t1,
|
| + {List<DartType> equivalents,
|
| + List<DartType> unrelated,
|
| + List<DartType> subtypes,
|
| + List<DartType> supertypes}) {
|
| + if (equivalents != null) {
|
| + for (DartType t2 in equivalents) {
|
| + _checkEquivalent(t1, t2);
|
| + }
|
| + }
|
| + if (unrelated != null) {
|
| + for (DartType t2 in unrelated) {
|
| + _checkUnrelated(t1, t2);
|
| + }
|
| + }
|
| + if (subtypes != null) {
|
| + for (DartType t2 in subtypes) {
|
| + _checkIsStrictSubtypeOf(t2, t1);
|
| + }
|
| + }
|
| + if (supertypes != null) {
|
| + for (DartType t2 in supertypes) {
|
| + _checkIsStrictSubtypeOf(t1, t2);
|
| + }
|
| + }
|
| + }
|
| +
|
| + void _checkUnrelated(DartType type1, DartType type2) {
|
| + _checkIsNotSubtypeOf(type1, type2);
|
| + _checkIsNotSubtypeOf(type2, type1);
|
| + }
|
| +
|
| + void _checkEquivalent(DartType type1, DartType type2) {
|
| + _checkIsSubtypeOf(type1, type2);
|
| + _checkIsSubtypeOf(type2, type1);
|
| + }
|
| +
|
| + void _checkIsStrictSubtypeOf(DartType type1, DartType type2) {
|
| + _checkIsSubtypeOf(type1, type2);
|
| + _checkIsNotSubtypeOf(type2, type1);
|
| + }
|
| +
|
| + void _checkIsSubtypeOf(DartType type1, DartType type2) {
|
| + expect(typeSystem.isSubtypeOf(type1, type2), true);
|
| + }
|
| +
|
| + void _checkIsNotSubtypeOf(DartType type1, DartType type2) {
|
| + expect(typeSystem.isSubtypeOf(type1, type2), false);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class StrongAssignabilityTest {
|
| + TypeProvider typeProvider;
|
| + TypeSystem typeSystem;
|
| +
|
| + DartType get bottomType => typeProvider.bottomType;
|
| + InterfaceType get doubleType => typeProvider.doubleType;
|
| + DartType get dynamicType => typeProvider.dynamicType;
|
| + InterfaceType get functionType => typeProvider.functionType;
|
| + InterfaceType get intType => typeProvider.intType;
|
| + InterfaceType get listType => typeProvider.listType;
|
| + InterfaceType get numType => typeProvider.numType;
|
| + InterfaceType get objectType => typeProvider.objectType;
|
| + InterfaceType get stringType => typeProvider.stringType;
|
| + DartType get voidType => VoidTypeImpl.instance;
|
| +
|
| + void setUp() {
|
| + typeProvider = new TestTypeProvider();
|
| + typeSystem = new StrongTypeSystemImpl();
|
| + }
|
| +
|
| + void test_isAssignableTo_dynamic_isTop() {
|
| + DartType interfaceType = ElementFactory.classElement2('A', []).type;
|
| + List<DartType> interassignable = <DartType>[
|
| + dynamicType,
|
| + objectType,
|
| + intType,
|
| + doubleType,
|
| + numType,
|
| + stringType,
|
| + interfaceType,
|
| + bottomType
|
| + ];
|
| + _checkGroups(dynamicType, interassignable: interassignable);
|
| + }
|
| +
|
| + void test_isAssignableTo_bottom_isBottom() {
|
| + DartType interfaceType = ElementFactory.classElement2('A', []).type;
|
| + List<DartType> interassignable = <DartType>[
|
| + dynamicType,
|
| + objectType,
|
| + intType,
|
| + doubleType,
|
| + numType,
|
| + stringType,
|
| + interfaceType,
|
| + bottomType
|
| + ];
|
| +
|
| + _checkGroups(bottomType, interassignable: interassignable);
|
| + }
|
| +
|
| + void test_isAssignableTo_int() {
|
| + DartType interfaceType = ElementFactory.classElement2('A', []).type;
|
| + List<DartType> interassignable = <DartType>[
|
| + dynamicType,
|
| + objectType,
|
| + intType,
|
| + numType,
|
| + bottomType
|
| + ];
|
| + List<DartType> unrelated = <DartType>[
|
| + doubleType,
|
| + stringType,
|
| + interfaceType,
|
| + ];
|
| +
|
| + _checkGroups(intType,
|
| + interassignable: interassignable, unrelated: unrelated);
|
| + }
|
| +
|
| + void test_isAssignableTo_double() {
|
| + DartType interfaceType = ElementFactory.classElement2('A', []).type;
|
| + List<DartType> interassignable = <DartType>[
|
| + dynamicType,
|
| + objectType,
|
| + doubleType,
|
| + numType,
|
| + bottomType
|
| + ];
|
| + List<DartType> unrelated = <DartType>[intType, stringType, interfaceType,];
|
| +
|
| + _checkGroups(doubleType,
|
| + interassignable: interassignable, unrelated: unrelated);
|
| + }
|
| +
|
| + void test_isAssignableTo_num() {
|
| + DartType interfaceType = ElementFactory.classElement2('A', []).type;
|
| + List<DartType> interassignable = <DartType>[
|
| + dynamicType,
|
| + objectType,
|
| + numType,
|
| + intType,
|
| + doubleType,
|
| + bottomType
|
| + ];
|
| + List<DartType> unrelated = <DartType>[stringType, interfaceType,];
|
| +
|
| + _checkGroups(numType,
|
| + interassignable: interassignable, unrelated: unrelated);
|
| + }
|
| +
|
| + void test_isAssignableTo_classes() {
|
| + ClassElement classTop = ElementFactory.classElement2("A");
|
| + ClassElement classLeft = ElementFactory.classElement("B", classTop.type);
|
| + ClassElement classRight = ElementFactory.classElement("C", classTop.type);
|
| + ClassElement classBottom = ElementFactory.classElement("D", classLeft.type)
|
| + ..interfaces = <InterfaceType>[classRight.type];
|
| + InterfaceType top = classTop.type;
|
| + InterfaceType left = classLeft.type;
|
| + InterfaceType right = classRight.type;
|
| + InterfaceType bottom = classBottom.type;
|
| +
|
| + _checkLattice(top, left, right, bottom);
|
| + }
|
| +
|
| + void test_isAssignableTo_simple_function() {
|
| + FunctionType top =
|
| + TypeBuilder.functionType(<DartType>[intType], objectType);
|
| + FunctionType left = TypeBuilder.functionType(<DartType>[intType], intType);
|
| + FunctionType right =
|
| + TypeBuilder.functionType(<DartType>[objectType], objectType);
|
| + FunctionType bottom =
|
| + TypeBuilder.functionType(<DartType>[objectType], intType);
|
| +
|
| + _checkCrossLattice(top, left, right, bottom);
|
| + }
|
| +
|
| + void test_isAssignableTo_call_method() {
|
| + ClassElementImpl classBottom = ElementFactory.classElement2("B");
|
| + MethodElement methodBottom =
|
| + ElementFactory.methodElement("call", objectType, <DartType>[intType]);
|
| + classBottom.methods = <MethodElement>[methodBottom];
|
| +
|
| + DartType top = TypeBuilder.functionType(<DartType>[intType], objectType);
|
| + InterfaceType bottom = classBottom.type;
|
| +
|
| + _checkIsAssignableTo(top, bottom);
|
| + }
|
| +
|
| + void test_isAssignableTo_fuzzy_arrows() {
|
| + FunctionType top =
|
| + TypeBuilder.functionType(<DartType>[dynamicType], objectType);
|
| + FunctionType left =
|
| + TypeBuilder.functionType(<DartType>[objectType], objectType);
|
| + FunctionType right =
|
| + TypeBuilder.functionType(<DartType>[dynamicType], bottomType);
|
| + FunctionType bottom =
|
| + TypeBuilder.functionType(<DartType>[objectType], bottomType);
|
| +
|
| + _checkCrossLattice(top, left, right, bottom);
|
| + }
|
| +
|
| + void test_isAssignableTo_void_functions() {
|
| + FunctionType top = TypeBuilder.functionType(<DartType>[intType], voidType);
|
| + FunctionType bottom =
|
| + TypeBuilder.functionType(<DartType>[objectType], intType);
|
| +
|
| + _checkEquivalent(bottom, top);
|
| + }
|
| +
|
| + void test_isAssignableTo_named_optional() {
|
| + DartType r = TypeBuilder.functionType(<DartType>[intType], intType);
|
| + DartType o = TypeBuilder.functionType(<DartType>[], intType,
|
| + optional: <DartType>[intType]);
|
| + DartType n = TypeBuilder.functionType(<DartType>[], intType,
|
| + named: <String, DartType>{'x': intType});
|
| + DartType rr =
|
| + TypeBuilder.functionType(<DartType>[intType, intType], intType);
|
| + DartType ro = TypeBuilder.functionType(<DartType>[intType], intType,
|
| + optional: <DartType>[intType]);
|
| + DartType rn = TypeBuilder.functionType(<DartType>[intType], intType,
|
| + named: <String, DartType>{'x': intType});
|
| + DartType oo = TypeBuilder.functionType(<DartType>[], intType,
|
| + optional: <DartType>[intType, intType]);
|
| + DartType nn = TypeBuilder.functionType(<DartType>[], intType,
|
| + named: <String, DartType>{'x': intType, 'y': intType});
|
| + DartType nnn = TypeBuilder.functionType(<DartType>[], intType,
|
| + named: <String, DartType>{'x': intType, 'y': intType, 'z': intType});
|
| +
|
| + _checkGroups(r,
|
| + interassignable: [r, o, ro, rn, oo], unrelated: [n, rr, nn, nnn]);
|
| + _checkGroups(o,
|
| + interassignable: [o, oo], unrelated: [n, rr, ro, rn, nn, nnn]);
|
| + _checkGroups(n,
|
| + interassignable: [n, nn, nnn], unrelated: [r, o, rr, ro, rn, oo]);
|
| + _checkGroups(rr,
|
| + interassignable: [rr, ro, oo], unrelated: [r, o, n, rn, nn, nnn]);
|
| + _checkGroups(ro, interassignable: [ro, oo], unrelated: [o, n, rn, nn, nnn]);
|
| + _checkGroups(rn,
|
| + interassignable: [rn], unrelated: [o, n, rr, ro, oo, nn, nnn]);
|
| + _checkGroups(oo, interassignable: [oo], unrelated: [n, rn, nn, nnn]);
|
| + _checkGroups(nn,
|
| + interassignable: [nn, nnn], unrelated: [r, o, rr, ro, rn, oo]);
|
| + _checkGroups(nnn,
|
| + interassignable: [nnn], unrelated: [r, o, rr, ro, rn, oo]);
|
| + }
|
| +
|
| + void test_isAssignableTo_generics() {
|
| + ClassElementImpl LClass = ElementFactory.classElement2('L', ["T"]);
|
| + InterfaceType LType = LClass.type;
|
| + ClassElementImpl MClass = ElementFactory.classElement2('M', ["T"]);
|
| + DartType typeParam = MClass.typeParameters[0].type;
|
| + InterfaceType superType = LType.substitute4(<DartType>[typeParam]);
|
| + MClass.interfaces = <InterfaceType>[superType];
|
| + InterfaceType MType = MClass.type;
|
| +
|
| + InterfaceType top = LType.substitute4(<DartType>[dynamicType]);
|
| + InterfaceType left = MType.substitute4(<DartType>[dynamicType]);
|
| + InterfaceType right = LType.substitute4(<DartType>[intType]);
|
| + InterfaceType bottom = MType.substitute4(<DartType>[intType]);
|
| +
|
| + _checkCrossLattice(top, left, right, bottom);
|
| + }
|
| +
|
| + void _checkCrossLattice(
|
| + DartType top, DartType left, DartType right, DartType bottom) {
|
| + _checkGroups(top, interassignable: <DartType>[top, left, right, bottom]);
|
| + _checkGroups(left, interassignable: <DartType>[top, left, right, bottom]);
|
| + _checkGroups(right, interassignable: <DartType>[top, left, right, bottom]);
|
| + _checkGroups(bottom, interassignable: <DartType>[top, left, right, bottom]);
|
| + }
|
| +
|
| + void _checkLattice(
|
| + DartType top, DartType left, DartType right, DartType bottom) {
|
| + _checkGroups(top, interassignable: <DartType>[top, left, right, bottom]);
|
| + _checkGroups(left,
|
| + interassignable: <DartType>[top, left, bottom],
|
| + unrelated: <DartType>[right]);
|
| + _checkGroups(right,
|
| + interassignable: <DartType>[top, right, bottom],
|
| + unrelated: <DartType>[left]);
|
| + _checkGroups(bottom, interassignable: <DartType>[top, left, right, bottom]);
|
| + }
|
| +
|
| + void _checkGroups(DartType t1,
|
| + {List<DartType> interassignable, List<DartType> unrelated}) {
|
| + if (interassignable != null) {
|
| + for (DartType t2 in interassignable) {
|
| + _checkEquivalent(t1, t2);
|
| + }
|
| + }
|
| + if (unrelated != null) {
|
| + for (DartType t2 in unrelated) {
|
| + _checkUnrelated(t1, t2);
|
| + }
|
| + }
|
| + }
|
| +
|
| + void _checkUnrelated(DartType type1, DartType type2) {
|
| + _checkIsNotAssignableTo(type1, type2);
|
| + _checkIsNotAssignableTo(type2, type1);
|
| + }
|
| +
|
| + void _checkEquivalent(DartType type1, DartType type2) {
|
| + _checkIsAssignableTo(type1, type2);
|
| + _checkIsAssignableTo(type2, type1);
|
| + }
|
| +
|
| + void _checkIsStrictAssignableTo(DartType type1, DartType type2) {
|
| + _checkIsAssignableTo(type1, type2);
|
| + _checkIsNotAssignableTo(type2, type1);
|
| + }
|
| +
|
| + void _checkIsAssignableTo(DartType type1, DartType type2) {
|
| + expect(typeSystem.isAssignableTo(type1, type2), true);
|
| + }
|
| +
|
| + void _checkIsNotAssignableTo(DartType type1, DartType type2) {
|
| + expect(typeSystem.isAssignableTo(type1, type2), false);
|
| }
|
| }
|
|
|