| Index: sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
|
| ===================================================================
|
| --- sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart (revision 29416)
|
| +++ sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart (working copy)
|
| @@ -539,8 +539,22 @@
|
| Iterable<Element> oldTargets = targets;
|
| Selector typedSelector = computeTypedSelector(inferrer);
|
| inferrer.updateSelectorInTree(caller, call, typedSelector);
|
| - targets = inferrer.compiler.world.allFunctions.filter(typedSelector);
|
|
|
| + Compiler compiler = inferrer.compiler;
|
| + Selector selectorToUse = typedSelector.extendIfReachesAll(compiler);
|
| +
|
| + bool canReachAll = compiler.enabledInvokeOn
|
| + && (selectorToUse != typedSelector);
|
| +
|
| + // If this call could potentially reach all methods that satisfy
|
| + // the untyped selector (through noSuchMethod's `Invocation`
|
| + // and a call to `delegate`), we iterate over all these methods to
|
| + // update their parameter types.
|
| + targets = compiler.world.allFunctions.filter(selectorToUse);
|
| + Iterable<Element> typedTargets = canReachAll
|
| + ? compiler.world.allFunctions.filter(typedSelector)
|
| + : targets;
|
| +
|
| // Walk over the found targets, and compute the joined union type mask
|
| // for all these targets.
|
| TypeMask newType = inferrer.types.joinTypeMasks(targets.map((element) {
|
| @@ -553,6 +567,15 @@
|
| this, element, arguments, typedSelector, remove: false);
|
| }
|
|
|
| + // If [canReachAll] is true, then we are iterating over all
|
| + // targets that satisfy the untyped selector. We skip the return
|
| + // type of the targets that can only be reached through
|
| + // `Invocation.delegate`. Note that the `noSuchMethod` targets
|
| + // are included in [typedTargets].
|
| + if (canReachAll && !typedTargets.contains(element)) {
|
| + return const TypeMask.nonNullEmpty();
|
| + }
|
| +
|
| if (returnsElementType(typedSelector)) {
|
| ContainerTypeMask mask = receiver.type;
|
| return mask.elementType;
|
| @@ -576,6 +599,7 @@
|
| this, element, arguments, typedSelector, remove: true);
|
| }
|
| });
|
| +
|
| return newType;
|
| }
|
|
|
|
|