From c1b102a94dbc6a7a0ffe022d4bef26f9390a90f2 Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Thu, 5 Nov 2015 11:14:47 +0100 Subject: [PATCH] Revert "Normalize type masks to use the least upper instantiated subclass/type." This reverts commit d3c68df8532fee63cd846fda7130d28c99c591df. BUG= Review URL: https://codereview.chromium.org/1431513010. --- pkg/compiler/lib/src/closure.dart | 3 - .../lib/src/cps_ir/type_mask_system.dart | 110 ++---- pkg/compiler/lib/src/enqueue.dart | 15 +- .../src/inferrer/simple_types_inferrer.dart | 14 +- pkg/compiler/lib/src/ssa/builder.dart | 10 +- .../lib/src/types/flat_type_mask.dart | 5 +- pkg/compiler/lib/src/types/type_mask.dart | 58 +-- pkg/compiler/lib/src/universe/class_set.dart | 94 +---- .../lib/src/universe/function_set.dart | 5 +- pkg/compiler/lib/src/universe/universe.dart | 27 ++ pkg/compiler/lib/src/world.dart | 105 ++---- tests/compiler/dart2js/members_test.dart | 20 +- tests/compiler/dart2js/mock_libraries.dart | 2 +- tests/compiler/dart2js/patch_test.dart | 1 - .../dart2js/type_combination_test.dart | 27 +- tests/compiler/dart2js/type_mask2_test.dart | 350 +++++++----------- tests/compiler/dart2js/union_type_test.dart | 33 +- 17 files changed, 292 insertions(+), 587 deletions(-) diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart index 9b9d6033050..00cb34ca1a6 100644 --- a/pkg/compiler/lib/src/closure.dart +++ b/pkg/compiler/lib/src/closure.dart @@ -998,9 +998,6 @@ class ClosureTranslator extends Visitor { String closureName = computeClosureName(element); ClosureClassElement globalizedElement = new ClosureClassElement( node, closureName, compiler, element); - // Extend [globalizedElement] as an instantiated class in the closed world. - compiler.world.registerClass( - globalizedElement, isDirectlyInstantiated: true); FunctionElement callElement = new SynthesizedCallMethodElementX(Identifiers.call, element, diff --git a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart index c1230bfd128..f8f562cad7f 100644 --- a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart +++ b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart @@ -25,13 +25,6 @@ class TypeMaskSystem { final World classWorld; final JavaScriptBackend backend; - TypeMask _numStringBoolType; - TypeMask _fixedLengthType; - TypeMask _interceptorType; - TypeMask _interceptedTypes; // Does not include null. - - TypeMask __indexableTypeTest; - TypeMask get dynamicType => inferrer.dynamicType; TypeMask get typeType => inferrer.typeType; TypeMask get functionType => inferrer.functionType; @@ -50,70 +43,12 @@ class TypeMaskSystem { TypeMask get uint32Type => inferrer.uint32Type; TypeMask get uintType => inferrer.positiveIntType; - TypeMask get numStringBoolType { - if (_numStringBoolType == null) { - // Build the number+string+bool type. To make containment tests more - // inclusive, we use the num, String, bool types for this, not - // the JSNumber, JSString, JSBool subclasses. - TypeMask anyNum = - new TypeMask.nonNullSubtype(classWorld.numClass, classWorld); - TypeMask anyString = - new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld); - TypeMask anyBool = - new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld); - _numStringBoolType = - new TypeMask.unionOf([anyNum, anyString, anyBool], - classWorld); - } - return _numStringBoolType; - } + TypeMask numStringBoolType; + TypeMask fixedLengthType; + TypeMask interceptorType; + TypeMask interceptedTypes; // Does not include null. - TypeMask get fixedLengthType { - if (_fixedLengthType == null) { - List fixedLengthTypes = - [stringType, backend.fixedArrayType]; - if (classWorld.isInstantiated(helpers.typedArrayClass)) { - fixedLengthTypes.add(nonNullSubclass(helpers.typedArrayClass)); - } - _fixedLengthType = new TypeMask.unionOf(fixedLengthTypes, classWorld); - } - return _fixedLengthType; - } - - TypeMask get interceptorType { - if (_interceptorType == null) { - _interceptorType = - new TypeMask.nonNullSubtype(helpers.jsInterceptorClass, classWorld); - } - return _interceptorType; - } - - TypeMask get interceptedTypes { // Does not include null. - if (_interceptedTypes == null) { - // We redundantly include subtypes of num/string/bool as intercepted - // types, because the type system does not infer that their - // implementations are all subclasses of Interceptor. - _interceptedTypes = new TypeMask.unionOf( - [interceptorType, numStringBoolType], classWorld); - } - return _interceptedTypes; - } - - TypeMask get _indexableTypeTest { - if (__indexableTypeTest == null) { - // Make a TypeMask containing Indexable and (redundantly) subtypes of - // string because the type inference does not infer that all strings are - // indexables. - TypeMask indexable = - new TypeMask.nonNullSubtype(helpers.jsIndexableClass, classWorld); - TypeMask anyString = - new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld); - __indexableTypeTest = new TypeMask.unionOf( - [indexable, anyString], - classWorld); - } - return __indexableTypeTest; - } + TypeMask _indexableTypeTest; ClassElement get jsNullClass => helpers.jsNullClass; @@ -124,6 +59,41 @@ class TypeMaskSystem { : inferrer = compiler.typesTask, classWorld = compiler.world, backend = compiler.backend { + + // Build the number+string+bool type. To make containment tests more + // inclusive, we use the num, String, bool types for this, not + // the JSNumber, JSString, JSBool subclasses. + TypeMask anyNum = + new TypeMask.nonNullSubtype(classWorld.numClass, classWorld); + TypeMask anyString = + new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld); + TypeMask anyBool = + new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld); + numStringBoolType = + new TypeMask.unionOf([anyNum, anyString, anyBool], + classWorld); + interceptorType = + new TypeMask.nonNullSubtype(helpers.jsInterceptorClass, classWorld); + + // We redundantly include subtypes of num/string/bool as intercepted types, + // because the type system does not infer that their implementations are + // all subclasses of Interceptor. + interceptedTypes = new TypeMask.unionOf( + [interceptorType, numStringBoolType], classWorld); + + TypeMask typedArray = nonNullSubclass(helpers.typedArrayClass); + fixedLengthType = new TypeMask.unionOf( + [stringType, backend.fixedArrayType, typedArray], + classWorld); + + // Make a TypeMask containing Indexable and (redundantly) subtypes of + // string because the type inference does not infer that all strings are + // indexables. + TypeMask indexable = + new TypeMask.nonNullSubtype(helpers.jsIndexableClass, classWorld); + _indexableTypeTest = new TypeMask.unionOf( + [indexable, anyString], + classWorld); } bool methodUsesReceiverArgument(FunctionElement function) { diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart index 878898901ab..39ec4385cef 100644 --- a/pkg/compiler/lib/src/enqueue.dart +++ b/pkg/compiler/lib/src/enqueue.dart @@ -178,19 +178,15 @@ abstract class Enqueuer { task.measure(() { ClassElement cls = type.element; cls.ensureResolved(resolution); - bool isNative = compiler.backend.isNative(cls); universe.registerTypeInstantiation( type, - isNative: isNative, + isNative: compiler.backend.isNative(cls), byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { compiler.backend.registerImplementedClass( cls, this, compiler.globalDependencies); }); - // TODO(johnniwinther): Share this reasoning with [Universe]. - if (!cls.isAbstract || isNative || mirrorUsage) { - processInstantiatedClass(cls); - } + processInstantiatedClass(cls); }); } @@ -339,10 +335,9 @@ abstract class Enqueuer { superclass, this, compiler.globalDependencies); } - ClassElement superclass = cls; - while (superclass != null) { - processClass(superclass); - superclass = superclass.superclass; + while (cls != null) { + processClass(cls); + cls = cls.superclass; } }); } diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart index 61f8595ff3a..08826d0aa95 100644 --- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart +++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart @@ -647,19 +647,7 @@ class SimpleTypeInferrerVisitor } }); } - if (analyzedElement.isGenerativeConstructor && cls.isAbstract) { - if (compiler.world.isDirectlyInstantiated(cls)) { - returnType = types.nonNullExact(cls); - } else if (compiler.world.isIndirectlyInstantiated(cls)) { - returnType = types.nonNullSubclass(cls); - } else { - // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this - // case; it's never called. - returnType = types.nonNullEmpty(); - } - } else { - returnType = types.nonNullExact(cls); - } + returnType = types.nonNullExact(cls); } else { signature.forEachParameter((LocalParameterElement element) { locals.update(element, inferrer.typeOfElement(element), node); diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart index 5e89a0080dc..35cf64c929b 100644 --- a/pkg/compiler/lib/src/ssa/builder.dart +++ b/pkg/compiler/lib/src/ssa/builder.dart @@ -3247,7 +3247,7 @@ class SsaBuilder extends ast.Visitor }); TypeMask type = - new TypeMask.nonNullExact(closureClassElement, compiler.world); + new TypeMask.nonNullExact(coreClasses.functionClass, compiler.world); push(new HForeignNew(closureClassElement, type, capturedVariables) ..sourceInformation = sourceInformationBuilder.buildCreate(node)); @@ -5074,13 +5074,7 @@ class SsaBuilder extends ast.Visitor : inferred; } else if (element.isGenerativeConstructor) { ClassElement cls = element.enclosingClass; - if (cls.isAbstract) { - // An error will be thrown. - return new TypeMask.nonNullEmpty(); - } else { - return new TypeMask.nonNullExact( - cls.thisType.element, compiler.world); - } + return new TypeMask.nonNullExact(cls.thisType.element, compiler.world); } else { return TypeMaskFactory.inferredReturnTypeForElement( originalElement, compiler); diff --git a/pkg/compiler/lib/src/types/flat_type_mask.dart b/pkg/compiler/lib/src/types/flat_type_mask.dart index 6516d96eed4..ce19f17c8b2 100644 --- a/pkg/compiler/lib/src/types/flat_type_mask.dart +++ b/pkg/compiler/lib/src/types/flat_type_mask.dart @@ -546,8 +546,9 @@ class FlatTypeMask implements TypeMask { */ static bool hasConcreteMatch(ClassElement cls, Selector selector, - ClassWorld world) { - assert(invariant(cls, world.isInstantiated(cls), + World world) { + assert(invariant(cls, + world.compiler.resolverWorld.isInstantiated(cls), message: '$cls has not been instantiated.')); Element element = findMatchIn(cls, selector); if (element == null) return false; diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/types/type_mask.dart index e5c1dc7d41d..2f5754fd880 100644 --- a/pkg/compiler/lib/src/types/type_mask.dart +++ b/pkg/compiler/lib/src/types/type_mask.dart @@ -89,7 +89,7 @@ abstract class TypeMask implements ReceiverConstraint { factory TypeMask.exact(ClassElement base, ClassWorld classWorld) { assert(invariant(base, classWorld.isInstantiated(base), message: () => "Cannot create exact type mask for uninstantiated " - "class $base.\n${classWorld.dump(base)}")); + "class $base.\n${classWorld.dump()}")); return new FlatTypeMask.exact(base); } @@ -99,31 +99,21 @@ abstract class TypeMask implements ReceiverConstraint { } factory TypeMask.subclass(ClassElement base, ClassWorld classWorld) { - assert(invariant(base, classWorld.isInstantiated(base), - message: () => "Cannot create subclass type mask for uninstantiated " - "class $base.\n${classWorld.dump(base)}")); - ClassElement topmost = classWorld.getLubOfInstantiatedSubclasses(base); - if (topmost == null) { - return new TypeMask.empty(); - } else if (classWorld.hasAnyStrictSubclass(topmost)) { - return new FlatTypeMask.subclass(topmost); + if (classWorld.hasAnyStrictSubclass(base)) { + return new FlatTypeMask.subclass(base); } else { - return new TypeMask.exact(topmost, classWorld); + return new TypeMask.exactOrEmpty(base, classWorld); } } factory TypeMask.subtype(ClassElement base, ClassWorld classWorld) { - ClassElement topmost = classWorld.getLubOfInstantiatedSubtypes(base); - if (topmost == null) { - return new TypeMask.empty(); + if (classWorld.hasOnlySubclasses(base)) { + return new TypeMask.subclass(base, classWorld); } - if (classWorld.hasOnlySubclasses(topmost)) { - return new TypeMask.subclass(topmost, classWorld); - } - if (classWorld.hasAnyStrictSubtype(topmost)) { - return new FlatTypeMask.subtype(topmost); + if (classWorld.hasAnyStrictSubtype(base)) { + return new FlatTypeMask.subtype(base); } else { - return new TypeMask.exact(topmost, classWorld); + return new TypeMask.exactOrEmpty(base, classWorld); } } @@ -131,8 +121,8 @@ abstract class TypeMask implements ReceiverConstraint { factory TypeMask.nonNullExact(ClassElement base, ClassWorld classWorld) { assert(invariant(base, classWorld.isInstantiated(base), - message: () => "Cannot create exact type mask for uninstantiated " - "class $base.\n${classWorld.dump(base)}")); + message: () => "Cannot create exact type mask for " + "uninstantiated class $base.\n${classWorld.dump(base)}")); return new FlatTypeMask.nonNullExact(base); } @@ -145,31 +135,21 @@ abstract class TypeMask implements ReceiverConstraint { } factory TypeMask.nonNullSubclass(ClassElement base, ClassWorld classWorld) { - assert(invariant(base, classWorld.isInstantiated(base), - message: () => "Cannot create subclass type mask for uninstantiated " - "class $base.\n${classWorld.dump(base)}")); - ClassElement topmost = classWorld.getLubOfInstantiatedSubclasses(base); - if (topmost == null) { - return new TypeMask.nonNullEmpty(); - } else if (classWorld.hasAnyStrictSubclass(topmost)) { - return new FlatTypeMask.nonNullSubclass(topmost); + if (classWorld.hasAnyStrictSubclass(base)) { + return new FlatTypeMask.nonNullSubclass(base); } else { - return new TypeMask.nonNullExact(topmost, classWorld); + return new TypeMask.nonNullExactOrEmpty(base, classWorld); } } factory TypeMask.nonNullSubtype(ClassElement base, ClassWorld classWorld) { - ClassElement topmost = classWorld.getLubOfInstantiatedSubtypes(base); - if (topmost == null) { - return new TypeMask.nonNullEmpty(); + if (classWorld.hasOnlySubclasses(base)) { + return new TypeMask.nonNullSubclass(base, classWorld); } - if (classWorld.hasOnlySubclasses(topmost)) { - return new TypeMask.nonNullSubclass(topmost, classWorld); - } - if (classWorld.hasAnyStrictSubtype(topmost)) { - return new FlatTypeMask.nonNullSubtype(topmost); + if (classWorld.hasAnyStrictSubtype(base)) { + return new FlatTypeMask.nonNullSubtype(base); } else { - return new TypeMask.nonNullExact(topmost, classWorld); + return new TypeMask.nonNullExactOrEmpty(base, classWorld); } } diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart index ac856a2802b..b4189767efb 100644 --- a/pkg/compiler/lib/src/universe/class_set.dart +++ b/pkg/compiler/lib/src/universe/class_set.dart @@ -35,7 +35,6 @@ import '../util/util.dart' show Link; /// class ClassHierarchyNode { final ClassElement cls; - ClassElement _leastUpperInstantiatedSubclass; /// `true` if [cls] has been directly instantiated. /// @@ -102,55 +101,15 @@ class ClassHierarchyNode { includeUninstantiated: includeUninstantiated); } - /// Returns the most specific subclass of [cls] (including [cls]) that is - /// directly instantiated or a superclass of all directly instantiated - /// subclasses. If [cls] is not instantiated, `null` is returned. - ClassElement getLubOfInstantiatedSubclasses() { - if (!isInstantiated) return null; - if (_leastUpperInstantiatedSubclass == null) { - _leastUpperInstantiatedSubclass = - _computeLeastUpperInstantiatedSubclass(); - } - return _leastUpperInstantiatedSubclass; - } - - ClassElement _computeLeastUpperInstantiatedSubclass() { - if (isDirectlyInstantiated) { - return cls; - } - ClassHierarchyNode subclass; - for (Link link = _directSubclasses; - !link.isEmpty; - link = link.tail) { - if (link.head.isInstantiated) { - if (subclass == null) { - subclass = link.head; - } else { - return cls; - } - } - } - if (subclass != null) { - return subclass.getLubOfInstantiatedSubclasses(); - } - return cls; - } - void printOn(StringBuffer sb, String indentation, {bool instantiatedOnly: false, - bool sorted: true, ClassElement withRespectTo}) { bool isRelatedTo(ClassElement subclass) { - return subclass == withRespectTo || - subclass.implementsInterface(withRespectTo); + return subclass.implementsInterface(withRespectTo); } - sb.write(indentation); - if (cls.isAbstract) { - sb.write('abstract '); - } - sb.write('class ${cls.name}:'); + sb.write('$indentation$cls'); if (isDirectlyInstantiated) { sb.write(' directly'); } @@ -161,14 +120,11 @@ class ClassHierarchyNode { if (_directSubclasses.isEmpty) { sb.write(']'); } else { - var subclasses = _directSubclasses; - if (sorted) { - subclasses = _directSubclasses.toList()..sort((a, b) { - return a.cls.name.compareTo(b.cls.name); - }); - } bool needsComma = false; - for (ClassHierarchyNode child in subclasses) { + for (Link link = _directSubclasses; + !link.isEmpty; + link = link.tail) { + ClassHierarchyNode child = link.head; if (instantiatedOnly && !child.isInstantiated) { continue; } @@ -184,7 +140,6 @@ class ClassHierarchyNode { sb, '$indentation ', instantiatedOnly: instantiatedOnly, - sorted: sorted, withRespectTo: withRespectTo); needsComma = true; } @@ -256,7 +211,6 @@ class ClassHierarchyNode { /// class ClassSet { final ClassHierarchyNode node; - ClassElement _leastUpperInstantiatedSubtype; List _directSubtypes; @@ -357,42 +311,6 @@ class ClassSet { } } - /// Returns the most specific subtype of [cls] (including [cls]) that is - /// directly instantiated or a superclass of all directly instantiated - /// subtypes. If no subtypes of [cls] are instantiated, `null` is returned. - ClassElement getLubOfInstantiatedSubtypes() { - if (_leastUpperInstantiatedSubtype == null) { - _leastUpperInstantiatedSubtype = _computeLeastUpperInstantiatedSubtype(); - } - return _leastUpperInstantiatedSubtype; - } - - ClassElement _computeLeastUpperInstantiatedSubtype() { - if (node.isDirectlyInstantiated) { - return cls; - } - if (_directSubtypes == null) { - return node.getLubOfInstantiatedSubclasses(); - } - ClassHierarchyNode subtype; - if (node.isInstantiated) { - subtype = node; - } - for (ClassHierarchyNode subnode in _directSubtypes) { - if (subnode.isInstantiated) { - if (subtype == null) { - subtype = subnode; - } else { - return cls; - } - } - } - if (subtype != null) { - return subtype.getLubOfInstantiatedSubclasses(); - } - return null; - } - String toString() { StringBuffer sb = new StringBuffer(); sb.write('[\n'); diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart index 9f13c1ea229..72a1813e91b 100644 --- a/pkg/compiler/lib/src/universe/function_set.dart +++ b/pkg/compiler/lib/src/universe/function_set.dart @@ -298,11 +298,8 @@ class FullFunctionSetQuery implements FunctionSetQuery { .map((cls) { if (classWorld.backend.isNullImplementation(cls)) { return const TypeMask.empty(); - } else if (classWorld.isInstantiated(cls.declaration)) { - return new TypeMask.nonNullSubclass(cls.declaration, classWorld); } else { - // TODO(johnniwinther): Avoid the need for this case. - return const TypeMask.empty(); + return new TypeMask.nonNullSubclass(cls.declaration, classWorld); } }), classWorld); diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart index c8e39a43242..5f9fd463248 100644 --- a/pkg/compiler/lib/src/universe/universe.dart +++ b/pkg/compiler/lib/src/universe/universe.dart @@ -124,6 +124,12 @@ class Universe { /// See [_directlyInstantiatedClasses]. final Set _instantiatedTypes = new Set(); + /// The set of all instantiated classes, either directly, as superclasses or + /// as supertypes. + /// + /// Invariant: Elements are declaration elements. + final Set _allInstantiatedClasses = new Set(); + /// Classes implemented by directly instantiated classes. final Set _implementedClasses = new Set(); @@ -200,6 +206,13 @@ class Universe { return _directlyInstantiatedClasses; } + /// All instantiated classes, either directly, as superclasses or as + /// supertypes. + // TODO(johnniwinther): Improve semantic precision. + Iterable get allInstantiatedClasses { + return _allInstantiatedClasses; + } + /// All directly instantiated types, that is, the types of the directly /// instantiated classes. /// @@ -207,6 +220,13 @@ class Universe { // TODO(johnniwinther): Improve semantic precision. Iterable get instantiatedTypes => _instantiatedTypes; + /// Returns `true` if [cls] is considered to be instantiated, either directly, + /// through subclasses. + // TODO(johnniwinther): Improve semantic precision. + bool isInstantiated(ClassElement cls) { + return _allInstantiatedClasses.contains(cls.declaration); + } + /// Returns `true` if [cls] is considered to be implemented by an /// instantiated class, either directly, through subclasses or through /// subtypes. The latter case only contains spurious information from @@ -251,6 +271,12 @@ class Universe { } }); } + while (cls != null) { + if (!_allInstantiatedClasses.add(cls)) { + return; + } + cls = cls.superclass; + } } bool _hasMatchingSelector(Map selectors, @@ -377,6 +403,7 @@ class Universe { fieldSetters.remove(element); fieldGetters.remove(element); _directlyInstantiatedClasses.remove(element); + _allInstantiatedClasses.remove(element); if (element is ClassElement) { assert(invariant( element, element.thisType.isRaw, diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart index b4860b88e4a..f04d10394c4 100644 --- a/pkg/compiler/lib/src/world.dart +++ b/pkg/compiler/lib/src/world.dart @@ -62,16 +62,9 @@ abstract class ClassWorld { /// The [ClassElement] for the [String] class defined in 'dart:core'. ClassElement get stringClass; - /// Returns `true` if [cls] is either directly or indirectly instantiated. + /// Returns `true` if [cls] is instantiated. bool isInstantiated(ClassElement cls); - /// Returns `true` if [cls] is directly instantiated. - bool isDirectlyInstantiated(ClassElement cls); - - /// Returns `true` if [cls] is indirectly instantiated, that is through a - /// subclass. - bool isIndirectlyInstantiated(ClassElement cls); - /// Returns `true` if [cls] is implemented by an instantiated class. bool isImplemented(ClassElement cls); @@ -113,16 +106,6 @@ abstract class ClassWorld { /// Returns `true` if all live classes that implement [cls] extend it. bool hasOnlySubclasses(ClassElement cls); - /// Returns the most specific subclass of [cls] (including [cls]) that is - /// directly instantiated or a superclass of all directly instantiated - /// subclasses. If [cls] is not instantiated, `null` is returned. - ClassElement getLubOfInstantiatedSubclasses(ClassElement cls); - - /// Returns the most specific subtype of [cls] (including [cls]) that is - /// directly instantiated or a superclass of all directly instantiated - /// subtypes. If no subtypes of [cls] are instantiated, `null` is returned. - ClassElement getLubOfInstantiatedSubtypes(ClassElement cls); - /// Returns an iterable over the common supertypes of the [classes]. Iterable commonSupertypesOf(Iterable classes); @@ -207,22 +190,10 @@ class World implements ClassWorld { return false; } - @override + /// Returns `true` if [cls] is instantiated either directly or through a + /// subclass. bool isInstantiated(ClassElement cls) { - ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; - return node != null && node.isInstantiated; - } - - @override - bool isDirectlyInstantiated(ClassElement cls) { - ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; - return node != null && node.isDirectlyInstantiated; - } - - @override - bool isIndirectlyInstantiated(ClassElement cls) { - ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; - return node != null && node.isIndirectlyInstantiated; + return compiler.resolverWorld.isInstantiated(cls); } /// Returns `true` if [cls] is implemented by an instantiated class. @@ -316,20 +287,6 @@ class World implements ClassWorld { return subclasses != null && (subclasses.length == subtypes.length); } - @override - ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { - ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; - return hierarchy != null - ? hierarchy.getLubOfInstantiatedSubclasses() : null; - } - - @override - ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) { - ClassSet classSet = _classSets[cls.declaration]; - return classSet != null - ? classSet.getLubOfInstantiatedSubtypes() : null; - } - /// Returns an iterable over the common supertypes of the [classes]. Iterable commonSupertypesOf(Iterable classes) { Iterator iterator = classes.iterator; @@ -486,11 +443,8 @@ class World implements ClassWorld { /// /// This ensures that class hierarchy queries can be performed on [cls] and /// classes that extend or implement it. - void registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) { + void registerClass(ClassElement cls) { _ensureClassSet(cls); - if (isDirectlyInstantiated) { - _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); - } } /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies @@ -538,36 +492,29 @@ class World implements ClassWorld { }); } - void _updateClassHierarchyNodeForClass( - ClassElement cls, - {bool directlyInstantiated: false, - bool indirectlyInstantiated: false}) { - ClassHierarchyNode node = getClassHierarchyNode(cls); - bool changed = false; - if (directlyInstantiated && !node.isDirectlyInstantiated) { - node.isDirectlyInstantiated = true; - changed = true; - } - if (indirectlyInstantiated && !node.isIndirectlyInstantiated) { - node.isIndirectlyInstantiated = true; - changed = true; - } - if (changed && cls.superclass != null) { - _updateClassHierarchyNodeForClass( - cls.superclass, indirectlyInstantiated: true); - } - // Ensure that classes implicitly implementing `Function` are in its - // subtype set. - if (cls != coreClasses.functionClass && - cls.implementsFunction(compiler)) { - ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); - subtypeSet.addSubtype(node); - } - } - void populate() { /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` /// properties of the [ClassHierarchyNode] for [cls]. + void updateClassHierarchyNodeForClass( + ClassElement cls, + {bool directlyInstantiated: false, + bool indirectlyInstantiated: false}) { + assert(!directlyInstantiated || isInstantiated(cls)); + ClassHierarchyNode node = getClassHierarchyNode(cls); + bool changed = false; + if (directlyInstantiated && !node.isDirectlyInstantiated) { + node.isDirectlyInstantiated = true; + changed = true; + } + if (indirectlyInstantiated && !node.isIndirectlyInstantiated) { + node.isIndirectlyInstantiated = true; + changed = true; + } + if (changed && cls.superclass != null) { + updateClassHierarchyNodeForClass( + cls.superclass, indirectlyInstantiated: true); + } + } void addSubtypes(ClassElement cls) { if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { @@ -578,7 +525,7 @@ class World implements ClassWorld { reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); } - _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); + updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); // Walk through the superclasses, and record the types // implemented by that type on the superclasses. diff --git a/tests/compiler/dart2js/members_test.dart b/tests/compiler/dart2js/members_test.dart index 59dbf971d91..d4be7ab42b2 100644 --- a/tests/compiler/dart2js/members_test.dart +++ b/tests/compiler/dart2js/members_test.dart @@ -12,7 +12,7 @@ import "package:compiler/src/elements/elements.dart" show Element, ClassElement, MemberSignature, Name, PublicName, DeclaredMember, Member; import "package:compiler/src/resolution/class_members.dart" - show MembersCreator, DeclaredMember, ErroneousMember, SyntheticMember; + show DeclaredMember, ErroneousMember, SyntheticMember; void main() { testClassMembers(); @@ -212,8 +212,6 @@ void testClassMembers() { functionType: env.functionType(String_, [])); InterfaceType A = env['A']; - MembersCreator.computeAllClassMembers(env.compiler, A.element); - checkMemberCount(A, 5 /*inherited*/ + 9 /*non-static declared*/, interfaceMembers: true); checkMemberCount(A, 5 /*inherited*/ + 9 /*non-abstract declared*/ + @@ -257,7 +255,6 @@ void testClassMembers() { isStatic: true, functionType: env.functionType(dynamic_, [])); ClassElement B = env.getElement('B'); - MembersCreator.computeAllClassMembers(env.compiler, B); InterfaceType B_this = B.thisType; TypeVariableType B_T = B_this.typeArguments.first; checkMemberCount(B_this, 4 /*inherited*/ + 4 /*non-static declared*/, @@ -283,7 +280,6 @@ void testClassMembers() { optionalParameters: [B_T])); ClassElement C = env.getElement('C'); - MembersCreator.computeAllClassMembers(env.compiler, C); InterfaceType C_this = C.thisType; TypeVariableType C_S = C_this.typeArguments.first; checkMemberCount(C_this, 8 /*inherited*/, interfaceMembers: true); @@ -310,7 +306,6 @@ void testClassMembers() { optionalParameters: [C_S])); InterfaceType D = env['D']; - MembersCreator.computeAllClassMembers(env.compiler, D.element); checkMemberCount(D, 8 /*inherited*/, interfaceMembers: true); checkMemberCount(D, 8 /*inherited*/, interfaceMembers: false); InterfaceType B_int = instantiate(B, [int_]); @@ -335,7 +330,6 @@ void testClassMembers() { optionalParameters: [int_])); InterfaceType E = env['E']; - MembersCreator.computeAllClassMembers(env.compiler, E.element); checkMemberCount(E, 8 /*inherited*/, interfaceMembers: true); checkMemberCount(E, 8 /*inherited*/, interfaceMembers: false); @@ -417,9 +411,6 @@ void testInterfaceMembers() { InterfaceType C = env['C']; InterfaceType D = env['D']; - // Ensure that members have been computed on all classes. - MembersCreator.computeAllClassMembers(env.compiler, D.element); - // A: num method1() // B: int method1() // D: dynamic method1() -- synthesized from A and B. @@ -585,9 +576,6 @@ void testClassVsInterfaceMembers() { InterfaceType B = env['B']; InterfaceType C = env['C']; - // Ensure that members have been computed on all classes. - MembersCreator.computeAllClassMembers(env.compiler, C.element); - // A: method1() // B: method1() // C class: method1() -- inherited from A. @@ -646,9 +634,6 @@ void testMixinMembers() { InterfaceType A_U = instantiate(A, [C_U]); InterfaceType B_V = instantiate(B, [C_V]); - // Ensure that members have been computed on all classes. - MembersCreator.computeAllClassMembers(env.compiler, C); - // A: method1() // B: method1() // C class: method1() -- inherited from A. @@ -717,9 +702,6 @@ void testMixinMembersWithoutImplements() { InterfaceType B = env['B']; InterfaceType C = env['C']; - // Ensure that members have been computed on all classes. - MembersCreator.computeAllClassMembers(env.compiler, C.element); - checkMember(C, 'm', checkType: NO_CLASS_MEMBER, inheritedFrom: A, functionType: env.functionType(dynamic_ , [])); diff --git a/tests/compiler/dart2js/mock_libraries.dart b/tests/compiler/dart2js/mock_libraries.dart index 9b89db0a89d..e73586c0cc0 100644 --- a/tests/compiler/dart2js/mock_libraries.dart +++ b/tests/compiler/dart2js/mock_libraries.dart @@ -63,7 +63,7 @@ const Map DEFAULT_CORE_LIBRARY = const { E get current => null; }''', 'LinkedHashMap': r''' - class LinkedHashMap implements Map { + class LinkedHashMap { factory LinkedHashMap._empty() => null; factory LinkedHashMap._literal(elements) => null; static _makeEmpty() => null; diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart index 3429a2c06da..7c3ca3d0525 100644 --- a/tests/compiler/dart2js/patch_test.dart +++ b/tests/compiler/dart2js/patch_test.dart @@ -914,7 +914,6 @@ Future testPatchAndSelector() async { """, runCompiler: true, analyzeOnly: true); World world = compiler.world; - world.populate(); ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find, expectIsPatched: true); diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart index 3aef5f82eb9..17af7f41efb 100644 --- a/tests/compiler/dart2js/type_combination_test.dart +++ b/tests/compiler/dart2js/type_combination_test.dart @@ -76,9 +76,8 @@ class RuleSet { var r1 = operate(type1, type2); var r2 = operate(type2, type1); - Expect.equals(result, r1, - "Unexpected result of $name($type1,$type2)"); - Expect.equals(r1, r2, 'Symmetry violation of $name($type1,$type2)'); + Expect.equals(result, r1); + Expect.equals(r1, r2, 'symmetry violation'); } void check(type1, type2, predicate) { @@ -732,11 +731,7 @@ void testRegressions(MockCompiler compiler) { } void main() { - asyncTest(() async { - MockCompiler compiler = new MockCompiler.internal(); - await compiler.init(""" - class PatternImpl implements Pattern {} - """); + asyncTest(() => MockCompiler.create((MockCompiler compiler) { JavaScriptBackend backend = compiler.backend; BackendHelpers helpers = backend.helpers; World world = compiler.world; @@ -749,9 +744,6 @@ void main() { compiler.globalDependencies); } }); - ClassElement patternImplClass = compiler.mainApp.find('PatternImpl'); - patternImplClass.ensureResolved(compiler.resolution); - backend.registerInstantiatedType( compiler.coreTypes.mapType(), compiler.enqueuer.resolution, @@ -760,10 +752,6 @@ void main() { compiler.coreTypes.functionType, compiler.enqueuer.resolution, compiler.globalDependencies); - backend.registerInstantiatedType( - patternImplClass.rawType, - compiler.enqueuer.resolution, - compiler.globalDependencies); compiler.world.populate(); // Grab hold of a supertype for String so we can produce potential @@ -817,15 +805,8 @@ void main() { dynamicType = new TypeMask.subclass( compiler.coreClasses.objectClass, world); - Expect.notEquals(emptyType, nonPrimitive1, - "nonPrimitive1 expected to be non-empty."); - Expect.notEquals(jsStringOrNull, potentialString, - "potentialString expected not to be exact JSString"); - Expect.notEquals(jsArrayOrNull, potentialArray, - "potentialArray expected not to be JSArray subclass"); - testUnion(compiler); testIntersection(compiler); testRegressions(compiler); - }); + })); } diff --git a/tests/compiler/dart2js/type_mask2_test.dart b/tests/compiler/dart2js/type_mask2_test.dart index 03db5802e15..25c19e10ce8 100644 --- a/tests/compiler/dart2js/type_mask2_test.dart +++ b/tests/compiler/dart2js/type_mask2_test.dart @@ -4,15 +4,12 @@ library type_mask2_test; -import 'dart:async'; import 'package:expect/expect.dart'; import 'package:async_helper/async_helper.dart'; import 'type_test_helper.dart'; import 'package:compiler/src/elements/elements.dart' show Element, ClassElement; import 'package:compiler/src/types/types.dart'; -import 'package:compiler/src/world.dart' show - ClassWorld; isCheckedMode() { try { @@ -25,67 +22,11 @@ isCheckedMode() { } void main() { - asyncTest(() async { - await testUnionTypeMaskFlatten(); - await testStringSubtypes(); - }); + testUnionTypeMaskFlatten(); } -checkMasks(ClassWorld classWorld, - List allClasses, - List masks, - {FlatTypeMask result, - List disjointMasks, - FlatTypeMask flattened, - List containedClasses}) { - List disjoint = []; - UnionTypeMask.unionOfHelper(masks, disjoint, classWorld); - Expect.listEquals(disjointMasks, disjoint, - 'Unexpected disjoint masks: $disjoint, expected $disjointMasks.'); - if (flattened == null) { - // We only do the invalid call to flatten in checked mode, as flatten's - // behaviour in unchecked mode is not defined and thus cannot be - // reliably tested. - if (isCheckedMode()) { - Expect.throws(() => UnionTypeMask.flatten(disjoint, classWorld), - (e) => e is AssertionError, - 'Expect assertion failure on flattening of $disjoint.'); - } - } else { - TypeMask flattenResult = - UnionTypeMask.flatten(disjoint, classWorld); - Expect.equals(flattened, flattenResult, - 'Unexpected flattening of $disjoint: ' - '$flattenResult, expected $flattened.'); - } - var union = UnionTypeMask.unionOf(masks, classWorld); - if (result == null) { - Expect.isTrue(union is UnionTypeMask, - 'Expected union of $masks to be a union-type: $union.'); - Expect.listEquals(disjointMasks, union.disjointMasks, - 'Unexpected union masks: ' - '${union.disjointMasks}, expected $disjointMasks.'); - } else { - Expect.equals(result, union, - 'Unexpected union of $masks: $union, expected $result.'); - } - if (containedClasses != null) { - for (ClassElement cls in allClasses) { - if (containedClasses.contains(cls)) { - Expect.isTrue(union.contains(cls, classWorld), - 'Expected $union to contain $cls.'); - } else { - Expect.isFalse(union.contains(cls, classWorld), - '$union not expected to contain $cls.'); - } - } - - } - return union; -} - -Future testUnionTypeMaskFlatten() async { - TypeEnvironment env = await TypeEnvironment.create(r""" +void testUnionTypeMaskFlatten() { + asyncTest(() => TypeEnvironment.create(r""" class A {} class B {} class C extends A {} @@ -101,158 +42,153 @@ Future testUnionTypeMaskFlatten() async { new E(); } """, - useMockCompiler: false); - - ClassWorld classWorld = env.compiler.world; - - ClassElement Object_ = env.getElement("Object"); - ClassElement A = env.getElement("A"); - ClassElement B = env.getElement("B"); - ClassElement C = env.getElement("C"); - ClassElement D = env.getElement("D"); - ClassElement E = env.getElement("E"); - - List allClasses = [Object_, A, B, C, D, E]; - - check(List masks, - {FlatTypeMask result, - List disjointMasks, - FlatTypeMask flattened, - List containedClasses}) { - return checkMasks( - classWorld, - allClasses, - masks, - result: result, - disjointMasks: disjointMasks, - flattened: flattened, - containedClasses: containedClasses); - } - - TypeMask empty = const TypeMask.nonNullEmpty(); - TypeMask subclassObject = new TypeMask.nonNullSubclass(Object_, classWorld); - TypeMask exactA = new TypeMask.nonNullExact(A, classWorld); - TypeMask subclassA = new TypeMask.nonNullSubclass(A, classWorld); - TypeMask subtypeA = new TypeMask.nonNullSubtype(A, classWorld); - TypeMask exactB = new TypeMask.nonNullExact(B, classWorld); - TypeMask subclassB = new TypeMask.nonNullSubclass(B, classWorld); - TypeMask exactC = new TypeMask.nonNullExact(C, classWorld); - TypeMask exactD = new TypeMask.nonNullExact(D, classWorld); - TypeMask exactE = new TypeMask.nonNullExact(E, classWorld); - - check([], - result: empty, - disjointMasks: [], - containedClasses: []); - - check([exactA], - result: exactA, - disjointMasks: [exactA], - containedClasses: [A]); - - check([exactA, exactA], - result: exactA, - disjointMasks: [exactA], - containedClasses: [A]); - - check([exactA, exactB], - disjointMasks: [exactA, exactB], - flattened: subclassObject, - containedClasses: [A, B]); - - check([subclassObject], - result: subclassObject, - disjointMasks: [subclassObject], - containedClasses: [Object_, A, B, C, D, E]); - - check([subclassObject, exactA], - disjointMasks: [subclassObject], - result: subclassObject, - containedClasses: [Object_, A, B, C, D, E]); - - check([exactA, exactC], - disjointMasks: [subclassA], - result: subclassA, - containedClasses: [A, C]); - - check([exactA, exactB, exactC], - disjointMasks: [subclassA, exactB], - flattened: subclassObject, - containedClasses: [A, B, C]); - - check([exactA, exactD], - disjointMasks: [subtypeA], - result: subtypeA, - containedClasses: [A, C, D, E]); - - check([exactA, exactB, exactD], - disjointMasks: [subtypeA, exactB], - flattened: subclassObject, - containedClasses: [A, B, C, D, E]); - - check([exactA, exactE], - disjointMasks: [subtypeA], - result: subtypeA, - containedClasses: [A, C, D, E]); - - check([exactA, exactB, exactE], - disjointMasks: [subtypeA, exactB], - flattened: subclassObject, - containedClasses: [A, B, C, D, E]); - - check([exactB, exactE, exactA], - disjointMasks: [subclassB, exactA], - flattened: subclassObject, - containedClasses: [A, B, E]); - - check([exactE, exactA, exactB], - disjointMasks: [subtypeA, exactB], - flattened: subclassObject, - containedClasses: [A, B, C, D, E]); - - check([exactE, exactB, exactA], - disjointMasks: [subclassB, exactA], - flattened: subclassObject, - containedClasses: [A, B, E]); -} - -Future testStringSubtypes() async { - TypeEnvironment env = await TypeEnvironment.create('', - mainSource: r""" - main() { - '' is String; - } - """, - useMockCompiler: false); + useMockCompiler: false).then((env) { var classWorld = env.compiler.world; - var backend = env.compiler.backend; ClassElement Object_ = env.getElement("Object"); - ClassElement String_ = env.getElement("String"); - ClassElement JSString = backend.helpers.jsStringClass; + ClassElement A = env.getElement("A"); + ClassElement B = env.getElement("B"); + ClassElement C = env.getElement("C"); + ClassElement D = env.getElement("D"); + ClassElement E = env.getElement("E"); - List allClasses = [Object_, String_]; + List allClasses = [Object_, A, B, C, D, E]; - Expect.isFalse(classWorld.isDirectlyInstantiated(Object_)); - Expect.isTrue(classWorld.isIndirectlyInstantiated(Object_)); - Expect.isTrue(classWorld.isInstantiated(Object_)); + check(List masks, + {FlatTypeMask result, + List disjointMasks, + FlatTypeMask flattened, + List containedClasses}) { + List disjoint = []; + UnionTypeMask.unionOfHelper(masks, disjoint, classWorld); + Expect.listEquals(disjointMasks, disjoint, + 'Unexpected disjoint masks: $disjoint, expected $disjointMasks.'); + if (flattened == null) { + // We only do the invalid call to flatten in checked mode, as flatten's + // brehaviour in unchecked more is not defined and thus cannot be + // reliably tested. + if (isCheckedMode()) { + Expect.throws(() => UnionTypeMask.flatten(disjoint, classWorld), + (e) => e is AssertionError, + 'Expect assertion failure on flattening of $disjoint.'); + } + } else { + TypeMask flattenResult = + UnionTypeMask.flatten(disjoint, classWorld); + Expect.equals(flattened, flattenResult, + 'Unexpected flattening of $disjoint: ' + '$flattenResult, expected $flattened.'); + } + var union = UnionTypeMask.unionOf(masks, classWorld); + if (result == null) { + Expect.isTrue(union is UnionTypeMask, + 'Expected union of $masks to be a union-type: $union.'); + Expect.listEquals(disjointMasks, union.disjointMasks, + 'Unexpected union masks: ' + '${union.disjointMasks}, expected $disjointMasks.'); + } else { + Expect.equals(result, union, + 'Unexpected union of $masks: $union, expected $result.'); + } + if (containedClasses != null) { + for (ClassElement cls in allClasses) { + if (containedClasses.contains(cls)) { + Expect.isTrue(union.contains(cls, classWorld), + 'Expected $union to contain $cls.'); + } else { + Expect.isFalse(union.contains(cls, classWorld), + '$union not expected to contain $cls.'); + } + } - Expect.isFalse(classWorld.isDirectlyInstantiated(String_)); - Expect.isFalse(classWorld.isIndirectlyInstantiated(String_)); - Expect.isFalse(classWorld.isInstantiated(String_)); + } + return union; + } - Expect.isTrue(classWorld.isDirectlyInstantiated(JSString)); - Expect.isFalse(classWorld.isIndirectlyInstantiated(JSString)); - Expect.isTrue(classWorld.isInstantiated(JSString)); + TypeMask empty = const TypeMask.nonNullEmpty(); + TypeMask subclassObject = new TypeMask.nonNullSubclass(Object_, classWorld); + TypeMask exactA = new TypeMask.nonNullExact(A, classWorld); + TypeMask subclassA = new TypeMask.nonNullSubclass(A, classWorld); + TypeMask subtypeA = new TypeMask.nonNullSubtype(A, classWorld); + TypeMask exactB = new TypeMask.nonNullExact(B, classWorld); + TypeMask subclassB = new TypeMask.nonNullSubclass(B, classWorld); + TypeMask exactC = new TypeMask.nonNullExact(C, classWorld); + TypeMask exactD = new TypeMask.nonNullExact(D, classWorld); + TypeMask exactE = new TypeMask.nonNullExact(E, classWorld); - TypeMask subtypeString = new TypeMask.nonNullSubtype(String_, classWorld); - TypeMask exactJSString = new TypeMask.nonNullExact(JSString, classWorld); - TypeMask subtypeJSString = - new TypeMask.nonNullSubtype(JSString, classWorld); - TypeMask subclassJSString = - new TypeMask.nonNullSubclass(JSString, classWorld); + check([], + result: empty, + disjointMasks: [], + containedClasses: []); - Expect.equals(exactJSString, subtypeString); - Expect.equals(exactJSString, subtypeJSString); - Expect.equals(exactJSString, subclassJSString); + check([exactA], + result: exactA, + disjointMasks: [exactA], + containedClasses: [A]); + + check([exactA, exactA], + result: exactA, + disjointMasks: [exactA], + containedClasses: [A]); + + check([exactA, exactB], + disjointMasks: [exactA, exactB], + flattened: subclassObject, + containedClasses: [A, B]); + + check([subclassObject], + result: subclassObject, + disjointMasks: [subclassObject], + containedClasses: [Object_, A, B, C, D, E]); + + check([subclassObject, exactA], + disjointMasks: [subclassObject], + result: subclassObject, + containedClasses: [Object_, A, B, C, D, E]); + + check([exactA, exactC], + disjointMasks: [subclassA], + result: subclassA, + containedClasses: [A, C]); + + check([exactA, exactB, exactC], + disjointMasks: [subclassA, exactB], + flattened: subclassObject, + containedClasses: [A, B, C]); + + check([exactA, exactD], + disjointMasks: [subtypeA], + result: subtypeA, + containedClasses: [A, C, D, E]); + + check([exactA, exactB, exactD], + disjointMasks: [subtypeA, exactB], + flattened: subclassObject, + containedClasses: [A, B, C, D, E]); + + check([exactA, exactE], + disjointMasks: [subtypeA], + result: subtypeA, + containedClasses: [A, C, D, E]); + + check([exactA, exactB, exactE], + disjointMasks: [subtypeA, exactB], + flattened: subclassObject, + containedClasses: [A, B, C, D, E]); + + check([exactB, exactE, exactA], + disjointMasks: [subclassB, exactA], + flattened: subclassObject, + containedClasses: [A, B, E]); + + check([exactE, exactA, exactB], + disjointMasks: [subtypeA, exactB], + flattened: subclassObject, + containedClasses: [A, B, C, D, E]); + + check([exactE, exactB, exactA], + disjointMasks: [subclassB, exactA], + flattened: subclassObject, + containedClasses: [A, B, E]); + })); } diff --git a/tests/compiler/dart2js/union_type_test.dart b/tests/compiler/dart2js/union_type_test.dart index 4ae2dac475c..584ad70e0b4 100644 --- a/tests/compiler/dart2js/union_type_test.dart +++ b/tests/compiler/dart2js/union_type_test.dart @@ -5,29 +5,22 @@ import "package:async_helper/async_helper.dart"; import "package:expect/expect.dart"; import "package:compiler/src/types/types.dart"; -import "package:compiler/src/world.dart"; -import 'type_test_helper.dart'; + +import "compiler_helper.dart"; main() { - - asyncTest(() async { - TypeEnvironment env = await TypeEnvironment.create(r""" - class A {} - class B {} - """, - mainSource: r""" + MockCompiler compiler = new MockCompiler.internal(analyzeOnly: true); + asyncTest(() => compiler.run(null, """ main() { - new A(); - new B(); + print(2); print("Hello"); } - """, - useMockCompiler: false); - World world = env.compiler.world; - world.populate(); - FlatTypeMask mask1 = new FlatTypeMask.exact(env.getElement('A')); - FlatTypeMask mask2 = new FlatTypeMask.exact(env.getElement('B')); - UnionTypeMask union1 = mask1.nonNullable().union(mask2, world); - UnionTypeMask union2 = mask2.nonNullable().union(mask1, world); + """).then((_) { + FlatTypeMask mask1 = + new FlatTypeMask.exact(compiler.coreClasses.intClass); + FlatTypeMask mask2 = + new FlatTypeMask.exact(compiler.coreClasses.stringClass); + UnionTypeMask union1 = mask1.nonNullable().union(mask2, compiler.world); + UnionTypeMask union2 = mask2.nonNullable().union(mask1, compiler.world); Expect.equals(union1, union2); - }); + })); }