Index: sdk/lib/_internal/compiler/implementation/universe/function_set.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/universe/function_set.dart (revision 26339) |
+++ sdk/lib/_internal/compiler/implementation/universe/function_set.dart (working copy) |
@@ -49,20 +49,28 @@ |
* that may be invoked with the given [selector]. |
*/ |
Iterable<Element> filter(Selector selector) { |
+ return query(selector).functions; |
+ } |
+ |
+ TypeMask receiverType(Selector selector) { |
+ return query(selector).computeMask(compiler); |
+ } |
+ |
+ FunctionSetQuery query(Selector selector) { |
SourceString name = selector.name; |
FunctionSetNode node = nodes[name]; |
FunctionSetNode noSuchMethods = nodes[Compiler.NO_SUCH_METHOD]; |
if (node != null) { |
- return node.query(selector, compiler, noSuchMethods).functions; |
+ return node.query(selector, compiler, noSuchMethods); |
} |
// If there is no method that matches [selector] we know we can |
// only hit [:noSuchMethod:]. |
- if (noSuchMethods == null) return const <Element>[]; |
+ if (noSuchMethods == null) return const FunctionSetQuery(const <Element>[]); |
selector = (selector.mask == null) |
? compiler.noSuchMethodSelector |
: new TypedSelector(selector.mask, compiler.noSuchMethodSelector); |
- return noSuchMethods.query(selector, compiler, null).functions; |
+ return noSuchMethods.query(selector, compiler, null); |
} |
void forEach(Function action) { |
@@ -186,11 +194,38 @@ |
FunctionSetQuery newQuery(Iterable<Element> functions, |
Selector selector, |
Compiler compiler) { |
- return new FunctionSetQuery(functions); |
+ return new FullFunctionSetQuery(functions); |
} |
} |
class FunctionSetQuery { |
final Iterable<Element> functions; |
+ TypeMask computeMask(Compiler compiler) => const TypeMask.nonNullEmpty(); |
const FunctionSetQuery(this.functions); |
} |
+ |
+class FullFunctionSetQuery extends FunctionSetQuery { |
+ TypeMask _mask; |
+ |
+ /** |
+ * Compute the type of all potential receivers of this function set. |
+ */ |
+ TypeMask computeMask(Compiler compiler) { |
+ if (_mask != null) return _mask; |
+ return _mask = new TypeMask.unionOf(functions |
+ .expand((element) { |
+ ClassElement cls = element.getEnclosingClass(); |
+ return compiler.world.isUsedAsMixin(cls) |
+ ? ([cls]..addAll(compiler.world.mixinUses[cls])) |
+ : [cls]; |
+ }) |
+ .map((cls) { |
+ return compiler.world.hasSubclasses(cls) |
+ ? new TypeMask.nonNullSubclass(cls.rawType) |
+ : new TypeMask.nonNullExact(cls.rawType); |
+ }), |
+ compiler); |
+ } |
+ |
+ FullFunctionSetQuery(functions) : super(functions); |
+} |