Index: pkg/compiler/lib/src/world.dart |
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart |
index 12bb5dcf3b5a30b91643183d655486654774d9ce..502ea8e9073d6de6b26250f58e5654a9e52679a0 100644 |
--- a/pkg/compiler/lib/src/world.dart |
+++ b/pkg/compiler/lib/src/world.dart |
@@ -66,6 +66,9 @@ abstract class ClassWorld { |
/// Returns `true` if [cls] is instantiated. |
bool isInstantiated(ClassElement cls); |
+ /// Returns `true` if [cls] is implemented by an instantiated class. |
+ bool isImplemented(ClassElement cls); |
+ |
/// Returns `true` if the class world is closed. |
bool get isClosed; |
@@ -123,6 +126,9 @@ abstract class ClassWorld { |
/// Returns `true` if closed-world assumptions can be made, that is, |
/// incremental compilation isn't enabled. |
bool get hasClosedWorldAssumption; |
+ |
+ /// Returns a string representation of the closed world. |
+ String dump(); |
} |
class World implements ClassWorld { |
@@ -145,10 +151,11 @@ class World implements ClassWorld { |
invariant(cls, cls.isDeclaration, |
message: '$cls must be the declaration.') && |
invariant(cls, cls.isResolved, |
- message: '$cls must be resolved.') && |
+ message: '$cls must be resolved.')/* && |
+ // TODO(johnniwinther): Reinsert this or similar invariant. |
(!mustBeInstantiated || |
invariant(cls, isInstantiated(cls), |
- message: '$cls is not instantiated.')); |
+ message: '$cls is not instantiated.'))*/; |
} |
/// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
@@ -178,11 +185,17 @@ class World implements ClassWorld { |
return false; |
} |
- /// Returns `true` if [cls] is instantiated. |
+ /// Returns `true` if [cls] is instantiated either directly or through a |
+ /// subclass. |
bool isInstantiated(ClassElement cls) { |
return compiler.resolverWorld.isInstantiated(cls); |
} |
+ /// Returns `true` if [cls] is implemented by an instantiated class. |
+ bool isImplemented(ClassElement cls) { |
+ return compiler.resolverWorld.isImplemented(cls); |
+ } |
+ |
/// Returns an iterable over the directly instantiated classes that extend |
/// [cls] possibly including [cls] itself, if it is live. |
Iterable<ClassElement> subclassesOf(ClassElement cls) { |
@@ -308,9 +321,23 @@ class World implements ClassWorld { |
if (_liveMixinUses == null) { |
_liveMixinUses = new Map<ClassElement, List<MixinApplicationElement>>(); |
for (ClassElement mixin in _mixinUses.keys) { |
- Iterable<MixinApplicationElement> uses = |
- _mixinUses[mixin].where(isInstantiated); |
- if (uses.isNotEmpty) _liveMixinUses[mixin] = uses.toList(); |
+ List<MixinApplicationElement> uses = <MixinApplicationElement>[]; |
+ |
+ void addLiveUse(MixinApplicationElement mixinApplication) { |
+ if (isInstantiated(mixinApplication)) { |
+ uses.add(mixinApplication); |
+ } else if (mixinApplication.isNamedMixinApplication) { |
+ List<MixinApplicationElement> next = _mixinUses[mixinApplication]; |
+ if (next != null) { |
+ next.forEach(addLiveUse); |
+ } |
+ } |
+ } |
+ |
+ _mixinUses[mixin].forEach(addLiveUse); |
+ if (uses.isNotEmpty) { |
+ _liveMixinUses[mixin] = uses; |
+ } |
} |
} |
Iterable<MixinApplicationElement> uses = _liveMixinUses[cls]; |
@@ -499,6 +526,15 @@ class World implements ClassWorld { |
compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes); |
} |
+ @override |
+ String dump() { |
+ StringBuffer sb = new StringBuffer(); |
+ sb.write("Instantiated classes in the closed world:\n"); |
+ getClassHierarchyNode(compiler.objectClass) |
+ .printOn(sb, ' ', instantiatedOnly: true); |
+ return sb.toString(); |
+ } |
+ |
void registerMixinUse(MixinApplicationElement mixinApplication, |
ClassElement mixin) { |
// TODO(johnniwinther): Add map restricted to live classes. |