| 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 747c803dc025f421ca53ac29c4c8f38d24bdf175..fd980dacbd5b778192ed8ebf2b40d5e5888d3713 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
|
| @@ -259,6 +259,87 @@ class TypeSchemaEnvironmentTest {
|
| expect(env.getGreatestLowerBound(A, B), same(bottomType));
|
| }
|
|
|
| + void test_instantiateToBounds_noTypesKnown() {
|
| + // class A {}
|
| + var A = _addClass(_class('A')).rawType;
|
| + // class B<T extends int> {}
|
| + var B = _addClass(
|
| + _class('B', typeParameters: [new TypeParameter('T', intType)]))
|
| + .thisType;
|
| + // class C<T extends int, S extends B<T>> {}
|
| + var C = () {
|
| + var T = new TypeParameter('T', intType);
|
| + var S = new TypeParameter(
|
| + 'S', new InterfaceType(B.classNode, [new TypeParameterType(T)]));
|
| + return _addClass(_class('C', typeParameters: [T, S])).thisType;
|
| + }();
|
| + // class D<T extends B<T>> {}
|
| + var D = () {
|
| + var T = new TypeParameter('T');
|
| + T.bound = new InterfaceType(B.classNode, [new TypeParameterType(T)]);
|
| + return _addClass(_class('D', typeParameters: [T])).thisType;
|
| + }();
|
| + // typedef T E<T extends int>();
|
| + var E = () {
|
| + var T = new TypeParameter('T', intType);
|
| + var typedefNode = new Typedef(
|
| + 'E', new FunctionType([], new TypeParameterType(T)),
|
| + typeParameters: [T]);
|
| + return new TypedefType(typedefNode, [new TypeParameterType(T)]);
|
| + }();
|
| + // class F<T> {}
|
| + var F = _addClass(
|
| + _class('F', typeParameters: [new TypeParameter('T', objectType)]))
|
| + .thisType;
|
| + var env = _makeEnv();
|
| + // A => A
|
| + expect(env.instantiateToBounds(A), same(A));
|
| + // B => B<int>
|
| + expect(
|
| + env.instantiateToBounds(B), new InterfaceType(B.classNode, [intType]));
|
| + // C => C<int, A<int>>
|
| + expect(
|
| + env.instantiateToBounds(C),
|
| + new InterfaceType(C.classNode, [
|
| + intType,
|
| + new InterfaceType(B.classNode, [intType])
|
| + ]));
|
| + // D => error
|
| + // However to allow analysis to continue D => D<dynamic>
|
| + // TODO(paulberry): check that an error is reported.
|
| + expect(env.instantiateToBounds(D), D.classNode.rawType);
|
| + // E => E<int> => () -> int
|
| + expect(
|
| + env.instantiateToBounds(E), new TypedefType(E.typedefNode, [intType]));
|
| + // F => F<dynamic>
|
| + expect(env.instantiateToBounds(F), F.classNode.rawType);
|
| + }
|
| +
|
| + void test_instantiateToBounds_typesKnown() {
|
| + // class A<T extends num> {}
|
| + var A = _addClass(
|
| + _class('A', typeParameters: [new TypeParameter('T', numType)]))
|
| + .thisType;
|
| + // class B<T extends A<T>> {}
|
| + var B = () {
|
| + var T = new TypeParameter('T');
|
| + T.bound = new InterfaceType(A.classNode, [new TypeParameterType(T)]);
|
| + return _addClass(_class('B', typeParameters: [T])).thisType;
|
| + }();
|
| + var env = _makeEnv();
|
| + // A => A<int> (if T known to be `int`)
|
| + expect(
|
| + env.instantiateToBounds(A,
|
| + knownTypes: {A.classNode.typeParameters[0]: intType}),
|
| + new InterfaceType(A.classNode, [intType]));
|
| + // Check that known types can be used to break circularities
|
| + // B => B<int> (if T known to be `int`)
|
| + expect(
|
| + env.instantiateToBounds(B,
|
| + knownTypes: {B.classNode.typeParameters[0]: intType}),
|
| + new InterfaceType(B.classNode, [intType]));
|
| + }
|
| +
|
| void test_lub_bottom() {
|
| var A = _addClass(_class('A')).rawType;
|
| var env = _makeEnv();
|
|
|