| Index: pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
|
| diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
|
| index 98b7251f5978b218685f6655d16f4b011936df62..747c803dc025f421ca53ac29c4c8f38d24bdf175 100644
|
| --- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
|
| +++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
|
| @@ -51,12 +51,46 @@ class TypeSchemaEnvironmentTest {
|
|
|
| Class get mapClass => coreTypes.mapClass;
|
|
|
| + InterfaceType get nullType => coreTypes.nullClass.rawType;
|
| +
|
| InterfaceType get numType => coreTypes.numClass.rawType;
|
|
|
| Class get objectClass => coreTypes.objectClass;
|
|
|
| InterfaceType get objectType => objectClass.rawType;
|
|
|
| + void test_addLowerBound() {
|
| + var A = _addClass(_class('A')).rawType;
|
| + var B =
|
| + _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
|
| + var C =
|
| + _addClass(_class('C', supertype: A.classNode.asThisSupertype)).rawType;
|
| + var env = _makeEnv();
|
| + var typeConstraint = new TypeConstraint();
|
| + expect(typeConstraint.lower, same(unknownType));
|
| + env.addLowerBound(typeConstraint, B);
|
| + expect(typeConstraint.lower, same(B));
|
| + env.addLowerBound(typeConstraint, C);
|
| + expect(typeConstraint.lower, same(A));
|
| + }
|
| +
|
| + void test_addUpperBound() {
|
| + var A = _addClass(_class('A')).rawType;
|
| + var B =
|
| + _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
|
| + var C =
|
| + _addClass(_class('C', supertype: A.classNode.asThisSupertype)).rawType;
|
| + var env = _makeEnv();
|
| + var typeConstraint = new TypeConstraint();
|
| + expect(typeConstraint.upper, same(unknownType));
|
| + env.addUpperBound(typeConstraint, A);
|
| + expect(typeConstraint.upper, same(A));
|
| + env.addUpperBound(typeConstraint, B);
|
| + expect(typeConstraint.upper, same(B));
|
| + env.addUpperBound(typeConstraint, C);
|
| + expect(typeConstraint.upper, same(bottomType));
|
| + }
|
| +
|
| void test_glb_bottom() {
|
| var A = _addClass(_class('A')).rawType;
|
| var env = _makeEnv();
|
| @@ -446,6 +480,122 @@ class TypeSchemaEnvironmentTest {
|
| expect(env.getGreatestLowerBound(unknownType, A), same(A));
|
| }
|
|
|
| + void test_solveTypeConstraint() {
|
| + var A = _addClass(_class('A')).rawType;
|
| + var B =
|
| + _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
|
| + var env = _makeEnv();
|
| + // Solve(? <: T <: ?) => ?
|
| + expect(env.solveTypeConstraint(_makeConstraint()), same(unknownType));
|
| + // Solve(? <: T <: ?, grounded) => Null
|
| + expect(
|
| + env.solveTypeConstraint(_makeConstraint(), grounded: true), nullType);
|
| + // Solve(A <: T <: ?) => A
|
| + expect(env.solveTypeConstraint(_makeConstraint(lower: A)), A);
|
| + // Solve(A <: T <: ?, grounded) => A
|
| + expect(
|
| + env.solveTypeConstraint(_makeConstraint(lower: A), grounded: true), A);
|
| + // Solve(A<?> <: T <: ?) => A<?>
|
| + expect(
|
| + env.solveTypeConstraint(_makeConstraint(
|
| + lower: new InterfaceType(A.classNode, [unknownType]))),
|
| + new InterfaceType(A.classNode, [unknownType]));
|
| + // Solve(A<?> <: T <: ?, grounded) => A<Object>
|
| + expect(
|
| + env.solveTypeConstraint(
|
| + _makeConstraint(
|
| + lower: new InterfaceType(A.classNode, [unknownType])),
|
| + grounded: true),
|
| + new InterfaceType(A.classNode, [objectType]));
|
| + // Solve(? <: T <: A) => A
|
| + expect(env.solveTypeConstraint(_makeConstraint(upper: A)), A);
|
| + // Solve(? <: T <: A, grounded) => A
|
| + expect(
|
| + env.solveTypeConstraint(_makeConstraint(upper: A), grounded: true), A);
|
| + // Solve(? <: T <: A<?>) => A<?>
|
| + expect(
|
| + env.solveTypeConstraint(_makeConstraint(
|
| + upper: new InterfaceType(A.classNode, [unknownType]))),
|
| + new InterfaceType(A.classNode, [unknownType]));
|
| + // Solve(? <: T <: A<?>, grounded) => A<Null>
|
| + expect(
|
| + env.solveTypeConstraint(
|
| + _makeConstraint(
|
| + upper: new InterfaceType(A.classNode, [unknownType])),
|
| + grounded: true),
|
| + new InterfaceType(A.classNode, [nullType]));
|
| + // Solve(B <: T <: A) => B
|
| + expect(env.solveTypeConstraint(_makeConstraint(lower: B, upper: A)), B);
|
| + // Solve(B <: T <: A, grounded) => B
|
| + expect(
|
| + env.solveTypeConstraint(_makeConstraint(lower: B, upper: A),
|
| + grounded: true),
|
| + B);
|
| + // Solve(B<?> <: T <: A) => A
|
| + expect(
|
| + env.solveTypeConstraint(_makeConstraint(
|
| + lower: new InterfaceType(B.classNode, [unknownType]), upper: A)),
|
| + A);
|
| + // Solve(B<?> <: T <: A, grounded) => A
|
| + expect(
|
| + env.solveTypeConstraint(
|
| + _makeConstraint(
|
| + lower: new InterfaceType(B.classNode, [unknownType]), upper: A),
|
| + grounded: true),
|
| + A);
|
| + // Solve(B <: T <: A<?>) => B
|
| + expect(
|
| + env.solveTypeConstraint(_makeConstraint(
|
| + lower: B, upper: new InterfaceType(A.classNode, [unknownType]))),
|
| + B);
|
| + // Solve(B <: T <: A<?>, grounded) => B
|
| + expect(
|
| + env.solveTypeConstraint(
|
| + _makeConstraint(
|
| + lower: B, upper: new InterfaceType(A.classNode, [unknownType])),
|
| + grounded: true),
|
| + B);
|
| + // Solve(B<?> <: T <: A<?>) => B<?>
|
| + expect(
|
| + env.solveTypeConstraint(_makeConstraint(
|
| + lower: new InterfaceType(B.classNode, [unknownType]),
|
| + upper: new InterfaceType(A.classNode, [unknownType]))),
|
| + new InterfaceType(B.classNode, [unknownType]));
|
| + // Solve(B<?> <: T <: A<?>) => B<Object>
|
| + expect(
|
| + env.solveTypeConstraint(
|
| + _makeConstraint(
|
| + lower: new InterfaceType(B.classNode, [unknownType]),
|
| + upper: new InterfaceType(A.classNode, [unknownType])),
|
| + grounded: true),
|
| + new InterfaceType(B.classNode, [objectType]));
|
| + }
|
| +
|
| + void test_typeConstraint_default() {
|
| + var typeConstraint = new TypeConstraint();
|
| + expect(typeConstraint.lower, same(unknownType));
|
| + expect(typeConstraint.upper, same(unknownType));
|
| + }
|
| +
|
| + void test_typeSatisfiesConstraint() {
|
| + var A = _addClass(_class('A')).rawType;
|
| + var B =
|
| + _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
|
| + var C =
|
| + _addClass(_class('C', supertype: B.classNode.asThisSupertype)).rawType;
|
| + var D =
|
| + _addClass(_class('D', supertype: C.classNode.asThisSupertype)).rawType;
|
| + var E =
|
| + _addClass(_class('E', supertype: D.classNode.asThisSupertype)).rawType;
|
| + var env = _makeEnv();
|
| + var typeConstraint = _makeConstraint(upper: B, lower: D);
|
| + expect(env.typeSatisfiesConstraint(A, typeConstraint), isFalse);
|
| + expect(env.typeSatisfiesConstraint(B, typeConstraint), isTrue);
|
| + expect(env.typeSatisfiesConstraint(C, typeConstraint), isTrue);
|
| + expect(env.typeSatisfiesConstraint(D, typeConstraint), isTrue);
|
| + expect(env.typeSatisfiesConstraint(E, typeConstraint), isFalse);
|
| + }
|
| +
|
| void test_unknown_at_bottom() {
|
| var A = _addClass(_class('A')).rawType;
|
| var env = _makeEnv();
|
| @@ -480,6 +630,14 @@ class TypeSchemaEnvironmentTest {
|
| DartType _list(DartType elementType) =>
|
| new InterfaceType(listClass, [elementType]);
|
|
|
| + TypeConstraint _makeConstraint(
|
| + {DartType lower: const UnknownType(),
|
| + DartType upper: const UnknownType()}) {
|
| + return new TypeConstraint()
|
| + ..lower = lower
|
| + ..upper = upper;
|
| + }
|
| +
|
| TypeSchemaEnvironment _makeEnv() {
|
| return new TypeSchemaEnvironment(coreTypes, new ClassHierarchy(program));
|
| }
|
|
|