| Index: pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
|
| diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
|
| index 48ae18195156335845eff5ffd7dc13d47e171ce7..10d105240add8b9cbd4b775d346e3b37f8f2e36e 100644
|
| --- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
|
| +++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
|
| @@ -63,7 +63,7 @@ abstract class TypeInformation {
|
| final MemberTypeInformation context;
|
|
|
| /// The element this [TypeInformation] node belongs to.
|
| - TypedElement get contextMember => context == null ? null : context.element;
|
| + TypedElement get contextMember => context == null ? null : context.member;
|
|
|
| Iterable<TypeInformation> get assignments => _assignments;
|
|
|
| @@ -206,7 +206,7 @@ abstract class TypeInformation {
|
| /// The [Element] where this [TypeInformation] was created. May be `null`
|
| /// for some [TypeInformation] nodes, where we do not need to store
|
| /// the information.
|
| - Element get owner => (context != null) ? context.element : null;
|
| + TypedElement get owner => (context != null) ? context.member : null;
|
|
|
| /// Returns whether the type cannot change after it has been
|
| /// inferred.
|
| @@ -343,7 +343,7 @@ class ParameterAssignments extends IterableBase<TypeInformation> {
|
| *
|
| */
|
| abstract class ElementTypeInformation extends TypeInformation {
|
| - final Element element;
|
| + final Element _element;
|
|
|
| /// Marker to disable inference for closures in [handleSpecialCases].
|
| bool disableInferenceForClosures = true;
|
| @@ -360,14 +360,18 @@ abstract class ElementTypeInformation extends TypeInformation {
|
| } else if (element.isLocal) {
|
| return new MemberTypeInformation._localFunction(element);
|
| }
|
| - return new MemberTypeInformation._member(element);
|
| + return new MemberTypeInformation._forMember(element);
|
| }
|
|
|
| - ElementTypeInformation._internal(MemberTypeInformation context, this.element)
|
| + ElementTypeInformation._internal(MemberTypeInformation context, this._element)
|
| : super(context);
|
| ElementTypeInformation._withAssignments(
|
| - MemberTypeInformation context, this.element, assignments)
|
| + MemberTypeInformation context, this._element, assignments)
|
| : super.withAssignments(context, assignments);
|
| +
|
| + String getInferredSignature(TypeSystem types);
|
| +
|
| + String get debugName;
|
| }
|
|
|
| /**
|
| @@ -383,7 +387,7 @@ abstract class ElementTypeInformation extends TypeInformation {
|
| */
|
| class MemberTypeInformation extends ElementTypeInformation
|
| with ApplyableTypeInformation {
|
| - TypedElement get element => super.element;
|
| + TypedElement get _member => super._element;
|
|
|
| /**
|
| * If [element] is a function, [closurizedCount] is the number of
|
| @@ -410,19 +414,41 @@ class MemberTypeInformation extends ElementTypeInformation
|
| MemberTypeInformation._internal(Element element)
|
| : super._internal(null, element);
|
|
|
| - MemberTypeInformation._member(MemberElement element)
|
| + MemberTypeInformation._forMember(MemberElement element)
|
| : this._internal(element);
|
|
|
| MemberTypeInformation._localFunction(LocalFunctionElement element)
|
| : this._internal(element);
|
|
|
| - void addCall(Element caller, Spannable node) {
|
| + TypedElement get member => _element;
|
| +
|
| + String get debugName => '$member';
|
| +
|
| + void addCallFromMember(MemberElement caller, Spannable node) {
|
| + _addCall(caller, node);
|
| + }
|
| +
|
| + @deprecated
|
| + void addCallFromLocalFunction(LocalFunctionElement caller, Spannable node) {
|
| + _addCall(caller, node);
|
| + }
|
| +
|
| + void _addCall(Element caller, Spannable node) {
|
| assert(node is ast.Node || node is Element);
|
| _callers ??= <Element, Setlet<Spannable>>{};
|
| _callers.putIfAbsent(caller, () => new Setlet()).add(node);
|
| }
|
|
|
| - void removeCall(Element caller, node) {
|
| + void removeCallFromMember(MemberElement caller, node) {
|
| + _removeCall(caller, node);
|
| + }
|
| +
|
| + @deprecated
|
| + void removeCallFromLocalFunction(LocalFunctionElement caller, node) {
|
| + _removeCall(caller, node);
|
| + }
|
| +
|
| + void _removeCall(Element caller, node) {
|
| if (_callers == null) return;
|
| Setlet calls = _callers[caller];
|
| if (calls == null) return;
|
| @@ -470,33 +496,33 @@ class MemberTypeInformation extends ElementTypeInformation
|
| bool get isStable => super.isStable && !isClosurized;
|
|
|
| TypeMask handleSpecialCases(InferrerEngine inferrer) {
|
| - if (element.isField &&
|
| + if (_member.isField &&
|
| (!inferrer.backend.canFieldBeUsedForGlobalOptimizations(
|
| - element, inferrer.closedWorld) ||
|
| - inferrer.assumeDynamic(element))) {
|
| + _member, inferrer.closedWorld) ||
|
| + inferrer.assumeDynamic(_member))) {
|
| // Do not infer types for fields that have a corresponding annotation or
|
| // are assigned by synthesized calls
|
|
|
| giveUp(inferrer);
|
| return safeType(inferrer);
|
| }
|
| - if (inferrer.isNativeMember(element)) {
|
| + if (inferrer.isNativeMember(_member)) {
|
| // Use the type annotation as the type for native elements. We
|
| // also give up on inferring to make sure this element never
|
| // goes in the work queue.
|
| giveUp(inferrer);
|
| - if (element.isField) {
|
| - FieldElement field = element;
|
| + if (_member.isField) {
|
| + FieldElement field = _member;
|
| return inferrer
|
| .typeOfNativeBehavior(inferrer.closedWorld.nativeData
|
| .getNativeFieldLoadBehavior(field))
|
| .type;
|
| } else {
|
| - assert(element.isFunction ||
|
| - element.isGetter ||
|
| - element.isSetter ||
|
| - element.isConstructor);
|
| - MethodElement methodElement = element;
|
| + assert(_member.isFunction ||
|
| + _member.isGetter ||
|
| + _member.isSetter ||
|
| + _member.isConstructor);
|
| + MethodElement methodElement = _member;
|
| var elementType = methodElement.type;
|
| if (elementType.kind != ResolutionTypeKind.FUNCTION) {
|
| return safeType(inferrer);
|
| @@ -510,8 +536,8 @@ class MemberTypeInformation extends ElementTypeInformation
|
| }
|
|
|
| CommonMasks commonMasks = inferrer.commonMasks;
|
| - if (element.isConstructor) {
|
| - ConstructorElement constructor = element;
|
| + if (_member.isConstructor) {
|
| + ConstructorElement constructor = _member;
|
| if (constructor.isIntFromEnvironmentConstructor) {
|
| giveUp(inferrer);
|
| return commonMasks.intType.nullable();
|
| @@ -530,19 +556,19 @@ class MemberTypeInformation extends ElementTypeInformation
|
| Compiler compiler = inferrer.compiler;
|
| if (!compiler.options.trustTypeAnnotations &&
|
| !compiler.options.enableTypeAssertions &&
|
| - !inferrer.trustTypeAnnotations(element)) {
|
| + !inferrer.trustTypeAnnotations(_member)) {
|
| return mask;
|
| }
|
| - if (element.isGenerativeConstructor || element.isSetter) {
|
| + if (_member.isGenerativeConstructor || _member.isSetter) {
|
| return mask;
|
| }
|
| - if (element.isField) {
|
| - return _narrowType(inferrer.closedWorld, mask, element.type);
|
| + if (_member.isField) {
|
| + return _narrowType(inferrer.closedWorld, mask, _member.type);
|
| }
|
| assert(
|
| - element.isFunction || element.isGetter || element.isFactoryConstructor);
|
| + _member.isFunction || _member.isGetter || _member.isFactoryConstructor);
|
|
|
| - ResolutionFunctionType type = element.type;
|
| + ResolutionFunctionType type = _member.type;
|
| return _narrowType(inferrer.closedWorld, mask, type.returnType);
|
| }
|
|
|
| @@ -557,7 +583,7 @@ class MemberTypeInformation extends ElementTypeInformation
|
| return potentiallyNarrowType(super.safeType(inferrer), inferrer);
|
| }
|
|
|
| - String toString() => 'MemberElement $element $type';
|
| + String toString() => 'MemberElement $_member $type';
|
|
|
| accept(TypeInformationVisitor visitor) {
|
| return visitor.visitMemberTypeInformation(this);
|
| @@ -566,11 +592,11 @@ class MemberTypeInformation extends ElementTypeInformation
|
| bool hasStableType(InferrerEngine inferrer) {
|
| // The number of assignments of non-final fields is
|
| // not stable. Therefore such a field cannot be stable.
|
| - if (element.isField && !(element.isConst || element.isFinal)) {
|
| + if (_member.isField && !(_member.isConst || _member.isFinal)) {
|
| return false;
|
| }
|
|
|
| - if (element.isFunction) return false;
|
| + if (_member.isFunction) return false;
|
|
|
| return super.hasStableType(inferrer);
|
| }
|
| @@ -582,6 +608,15 @@ class MemberTypeInformation extends ElementTypeInformation
|
| _callers = null;
|
| super.cleanup();
|
| }
|
| +
|
| + @override
|
| + String getInferredSignature(TypeSystem types) {
|
| + if (_member.isLocal) {
|
| + return types.getInferredSignatureOfLocalFunction(_member);
|
| + } else {
|
| + return types.getInferredSignatureOfMethod(_member);
|
| + }
|
| + }
|
| }
|
|
|
| /**
|
| @@ -594,31 +629,39 @@ class MemberTypeInformation extends ElementTypeInformation
|
| * the [ElementTypeInformation] factory.
|
| */
|
| class ParameterTypeInformation extends ElementTypeInformation {
|
| - ParameterElement get element => super.element;
|
| - FunctionElement get declaration => element.functionDeclaration;
|
| + ParameterElement get _parameter => super._element;
|
| + final FunctionElement _declaration;
|
| + // TODO(johnniwinther): This should be a [MethodElement].
|
| + final FunctionElement _method;
|
|
|
| - ParameterTypeInformation._internal(
|
| - MemberTypeInformation context, ParameterElement parameter)
|
| + ParameterTypeInformation._internal(MemberTypeInformation context,
|
| + ParameterElement parameter, this._declaration, this._method)
|
| : super._internal(context, parameter);
|
|
|
| factory ParameterTypeInformation._static(
|
| ParameterElement element, TypeSystem types) {
|
| - assert(!element.functionDeclaration.isInstanceMember);
|
| MethodElement method = element.functionDeclaration;
|
| + assert(!method.isInstanceMember);
|
| return new ParameterTypeInformation._internal(
|
| - types.getInferredTypeOfMember(method), element);
|
| + types.getInferredTypeOfMember(method), element, method, method);
|
| }
|
|
|
| factory ParameterTypeInformation._localFunction(
|
| ParameterElement element, TypeSystem types) {
|
| LocalFunctionElement localFunction = element.functionDeclaration;
|
| return new ParameterTypeInformation._internal(
|
| - types.getInferredTypeOfLocalFunction(localFunction), element);
|
| + types.getInferredTypeOfLocalFunction(localFunction),
|
| + element,
|
| + localFunction,
|
| + // TODO(johnniwinther): This should be `localFunction.callMethod`.
|
| + localFunction);
|
| }
|
|
|
| ParameterTypeInformation._instanceMember(
|
| ParameterElement element, TypeSystem types)
|
| - : super._withAssignments(
|
| + : _declaration = element.functionDeclaration,
|
| + _method = element.functionDeclaration,
|
| + super._withAssignments(
|
| types.getInferredTypeOfMember(
|
| element.functionDeclaration as MethodElement),
|
| element,
|
| @@ -626,22 +669,30 @@ class ParameterTypeInformation extends ElementTypeInformation {
|
| assert(element.functionDeclaration.isInstanceMember);
|
| }
|
|
|
| + // TODO(johnniwinther): This should be a [MethodElement].
|
| + FunctionElement get method => _method;
|
| +
|
| + Local get parameter => _parameter;
|
| +
|
| + String get debugName => '$parameter';
|
| +
|
| bool isTearOffClosureParameter = false;
|
|
|
| void tagAsTearOffClosureParameter(InferrerEngine inferrer) {
|
| - assert(element.isRegularParameter);
|
| + assert(_parameter.isRegularParameter);
|
| isTearOffClosureParameter = true;
|
| // We have to add a flow-edge for the default value (if it exists), as we
|
| // might not see all call-sites and thus miss the use of it.
|
| - TypeInformation defaultType = inferrer.getDefaultTypeOfParameter(element);
|
| + TypeInformation defaultType =
|
| + inferrer.getDefaultTypeOfParameter(_parameter);
|
| if (defaultType != null) defaultType.addUser(this);
|
| }
|
|
|
| // TODO(herhut): Cleanup into one conditional.
|
| TypeMask handleSpecialCases(InferrerEngine inferrer) {
|
| if (!inferrer.backend.canFunctionParametersBeUsedForGlobalOptimizations(
|
| - element.functionDeclaration, inferrer.closedWorld) ||
|
| - inferrer.assumeDynamic(declaration)) {
|
| + _method, inferrer.closedWorld) ||
|
| + inferrer.assumeDynamic(_method)) {
|
| // Do not infer types for parameters that have a corresponding annotation
|
| // or that are assigned by synthesized calls.
|
| giveUp(inferrer);
|
| @@ -650,9 +701,9 @@ class ParameterTypeInformation extends ElementTypeInformation {
|
|
|
| // The below do not apply to parameters of constructors, so skip
|
| // initializing formals.
|
| - if (element.isInitializingFormal) return null;
|
| + if (_parameter.isInitializingFormal) return null;
|
|
|
| - if ((isTearOffClosureParameter || declaration.isLocal) &&
|
| + if ((isTearOffClosureParameter || _declaration.isLocal) &&
|
| disableInferenceForClosures) {
|
| // Do not infer types for parameters of closures. We do not
|
| // clear the assignments in case the closure is successfully
|
| @@ -660,9 +711,9 @@ class ParameterTypeInformation extends ElementTypeInformation {
|
| giveUp(inferrer, clearAssignments: false);
|
| return safeType(inferrer);
|
| }
|
| - if (declaration.isInstanceMember &&
|
| - (declaration.name == Identifiers.noSuchMethod_ ||
|
| - (declaration.name == Identifiers.call &&
|
| + if (_declaration.isInstanceMember &&
|
| + (_declaration.name == Identifiers.noSuchMethod_ ||
|
| + (_declaration.name == Identifiers.call &&
|
| disableInferenceForClosures))) {
|
| // Do not infer types for parameters of [noSuchMethod] and
|
| // [call] instance methods.
|
| @@ -670,11 +721,11 @@ class ParameterTypeInformation extends ElementTypeInformation {
|
| return safeType(inferrer);
|
| }
|
| if (inferrer.closedWorldRefiner
|
| - .getCurrentlyKnownMightBePassedToApply(declaration)) {
|
| + .getCurrentlyKnownMightBePassedToApply(_method)) {
|
| giveUp(inferrer);
|
| return safeType(inferrer);
|
| }
|
| - if (declaration == inferrer.mainElement) {
|
| + if (_method == inferrer.mainElement) {
|
| // The implicit call to main is not seen by the inferrer,
|
| // therefore we explicitly set the type of its parameters as
|
| // dynamic.
|
| @@ -690,14 +741,14 @@ class ParameterTypeInformation extends ElementTypeInformation {
|
| TypeMask potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
|
| Compiler compiler = inferrer.compiler;
|
| if (!compiler.options.trustTypeAnnotations &&
|
| - !inferrer.trustTypeAnnotations(declaration)) {
|
| + !inferrer.trustTypeAnnotations(_method)) {
|
| return mask;
|
| }
|
| // When type assertions are enabled (aka checked mode), we have to always
|
| // ignore type annotations to ensure that the checks are actually inserted
|
| // into the function body and retained until runtime.
|
| assert(!compiler.options.enableTypeAssertions);
|
| - return _narrowType(inferrer.closedWorld, mask, element.type);
|
| + return _narrowType(inferrer.closedWorld, mask, _parameter.type);
|
| }
|
|
|
| TypeMask computeType(InferrerEngine inferrer) {
|
| @@ -714,7 +765,7 @@ class ParameterTypeInformation extends ElementTypeInformation {
|
| bool hasStableType(InferrerEngine inferrer) {
|
| // The number of assignments of parameters of instance methods is
|
| // not stable. Therefore such a parameter cannot be stable.
|
| - if (element.functionDeclaration.isInstanceMember) {
|
| + if (_declaration.isInstanceMember) {
|
| return false;
|
| }
|
| return super.hasStableType(inferrer);
|
| @@ -724,7 +775,12 @@ class ParameterTypeInformation extends ElementTypeInformation {
|
| return visitor.visitParameterTypeInformation(this);
|
| }
|
|
|
| - String toString() => 'ParameterElement $element $type';
|
| + String toString() => 'ParameterElement $_parameter $type';
|
| +
|
| + @override
|
| + String getInferredSignature(TypeSystem types) {
|
| + throw new UnsupportedError('ParameterTypeInformation.getInferredSignature');
|
| + }
|
| }
|
|
|
| /**
|
| @@ -740,7 +796,8 @@ class ParameterTypeInformation extends ElementTypeInformation {
|
| abstract class CallSiteTypeInformation extends TypeInformation
|
| with ApplyableTypeInformation {
|
| final Spannable call;
|
| - final Element caller;
|
| + // TODO(johnniwinther): [caller] should always be a [MemberElement].
|
| + final /*LocalFunctionElement|MemberElement*/ Element caller;
|
| final Selector selector;
|
| final TypeMask mask;
|
| final ArgumentsTypes arguments;
|
| @@ -766,6 +823,18 @@ class StaticCallSiteTypeInformation extends CallSiteTypeInformation {
|
| MemberTypeInformation context,
|
| Spannable call,
|
| Element enclosing,
|
| + MemberElement calledElement,
|
| + Selector selector,
|
| + TypeMask mask,
|
| + ArgumentsTypes arguments,
|
| + bool inLoop)
|
| + : this.internal(context, call, enclosing, calledElement, selector, mask,
|
| + arguments, inLoop);
|
| +
|
| + StaticCallSiteTypeInformation.internal(
|
| + MemberTypeInformation context,
|
| + Spannable call,
|
| + Element enclosing,
|
| this.calledElement,
|
| Selector selector,
|
| TypeMask mask,
|
| @@ -773,14 +842,17 @@ class StaticCallSiteTypeInformation extends CallSiteTypeInformation {
|
| bool inLoop)
|
| : super(context, call, enclosing, selector, mask, arguments, inLoop);
|
|
|
| + MemberTypeInformation _getCalledTypeInfo(InferrerEngine inferrer) {
|
| + return inferrer.types.getInferredTypeOfMember(calledElement);
|
| + }
|
| +
|
| void addToGraph(InferrerEngine inferrer) {
|
| - MemberTypeInformation callee;
|
| - if (calledElement.isLocal) {
|
| - callee = inferrer.types.getInferredTypeOfLocalFunction(calledElement);
|
| + MemberTypeInformation callee = _getCalledTypeInfo(inferrer);
|
| + if (caller.isLocal) {
|
| + callee.addCallFromLocalFunction(caller, call);
|
| } else {
|
| - callee = inferrer.types.getInferredTypeOfMember(calledElement);
|
| + callee.addCallFromMember(caller, call);
|
| }
|
| - callee.addCall(caller, call);
|
| callee.addUser(this);
|
| if (arguments != null) {
|
| arguments.forEach((info) => info.addUser(this));
|
| @@ -798,24 +870,16 @@ class StaticCallSiteTypeInformation extends CallSiteTypeInformation {
|
| return selector == null;
|
| }
|
|
|
| + TypeInformation _getCalledTypeInfoWithSelector(InferrerEngine inferrer) {
|
| + return inferrer.typeOfMemberWithSelector(calledElement, selector);
|
| + }
|
| +
|
| TypeMask computeType(InferrerEngine inferrer) {
|
| if (isSynthesized) {
|
| assert(arguments != null);
|
| - if (calledElement.isLocal) {
|
| - return inferrer.types
|
| - .getInferredTypeOfLocalFunction(calledElement)
|
| - .type;
|
| - } else {
|
| - return inferrer.types.getInferredTypeOfMember(calledElement).type;
|
| - }
|
| + return _getCalledTypeInfo(inferrer).type;
|
| } else {
|
| - if (calledElement.isLocal) {
|
| - return inferrer
|
| - .typeOfLocalFunctionWithSelector(calledElement, selector)
|
| - .type;
|
| - } else {
|
| - return inferrer.typeOfMemberWithSelector(calledElement, selector).type;
|
| - }
|
| + return _getCalledTypeInfoWithSelector(inferrer).type;
|
| }
|
| }
|
|
|
| @@ -826,25 +890,14 @@ class StaticCallSiteTypeInformation extends CallSiteTypeInformation {
|
| }
|
|
|
| bool hasStableType(InferrerEngine inferrer) {
|
| - bool isStable;
|
| - if (calledElement.isLocal) {
|
| - isStable =
|
| - inferrer.types.getInferredTypeOfLocalFunction(calledElement).isStable;
|
| - } else {
|
| - isStable = inferrer.types.getInferredTypeOfMember(calledElement).isStable;
|
| - }
|
| + bool isStable = _getCalledTypeInfo(inferrer).isStable;
|
| return isStable &&
|
| (arguments == null || arguments.every((info) => info.isStable)) &&
|
| super.hasStableType(inferrer);
|
| }
|
|
|
| void removeAndClearReferences(InferrerEngine inferrer) {
|
| - ElementTypeInformation callee;
|
| - if (calledElement.isLocal) {
|
| - callee = inferrer.types.getInferredTypeOfLocalFunction(calledElement);
|
| - } else {
|
| - callee = inferrer.types.getInferredTypeOfMember(calledElement);
|
| - }
|
| + ElementTypeInformation callee = _getCalledTypeInfo(inferrer);
|
| callee.removeUser(this);
|
| if (arguments != null) {
|
| arguments.forEach((info) => info.removeUser(this));
|
| @@ -853,6 +906,30 @@ class StaticCallSiteTypeInformation extends CallSiteTypeInformation {
|
| }
|
| }
|
|
|
| +@deprecated
|
| +class LocalFunctionCallSiteTypeInformation
|
| + extends StaticCallSiteTypeInformation {
|
| + LocalFunctionCallSiteTypeInformation(
|
| + MemberTypeInformation context,
|
| + Spannable call,
|
| + Element enclosing,
|
| + LocalFunctionElement calledElement,
|
| + Selector selector,
|
| + TypeMask mask,
|
| + ArgumentsTypes arguments,
|
| + bool inLoop)
|
| + : super.internal(context, call, enclosing, calledElement, selector, mask,
|
| + arguments, inLoop);
|
| +
|
| + MemberTypeInformation _getCalledTypeInfo(InferrerEngine inferrer) {
|
| + return inferrer.types.getInferredTypeOfLocalFunction(calledElement);
|
| + }
|
| +
|
| + TypeInformation _getCalledTypeInfoWithSelector(InferrerEngine inferrer) {
|
| + return inferrer.typeOfLocalFunctionWithSelector(calledElement, selector);
|
| + }
|
| +}
|
| +
|
| class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
|
| final TypeInformation receiver;
|
|
|
| @@ -881,7 +958,11 @@ class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
|
| for (MemberElement element in targets) {
|
| MemberTypeInformation callee =
|
| inferrer.types.getInferredTypeOfMember(element);
|
| - callee.addCall(caller, call);
|
| + if (caller.isLocal) {
|
| + callee.addCallFromLocalFunction(caller, call);
|
| + } else {
|
| + callee.addCallFromMember(caller, call);
|
| + }
|
| callee.addUser(this);
|
| inferrer.updateParameterAssignments(
|
| this, element, arguments, selector, typeMask,
|
| @@ -1028,7 +1109,11 @@ class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
|
| TypeMask computeType(InferrerEngine inferrer) {
|
| Iterable<MemberEntity> oldTargets = targets;
|
| TypeMask typeMask = computeTypedSelector(inferrer);
|
| - inferrer.updateSelectorInTree(caller, call, selector, typeMask);
|
| + if (caller.isLocal) {
|
| + inferrer.updateSelectorInLocalFunction(caller, call, selector, typeMask);
|
| + } else {
|
| + inferrer.updateSelectorInMember(caller, call, selector, typeMask);
|
| + }
|
|
|
| TypeMask maskToUse =
|
| inferrer.closedWorld.extendMaskIfReachesAll(selector, typeMask);
|
| @@ -1053,7 +1138,11 @@ class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
|
| MemberElement element = _element;
|
| MemberTypeInformation callee =
|
| inferrer.types.getInferredTypeOfMember(element);
|
| - callee.addCall(caller, call);
|
| + if (caller.isLocal) {
|
| + callee.addCallFromLocalFunction(caller, call);
|
| + } else {
|
| + callee.addCallFromMember(caller, call);
|
| + }
|
| callee.addUser(this);
|
| inferrer.updateParameterAssignments(
|
| this, element, arguments, selector, typeMask,
|
| @@ -1067,7 +1156,11 @@ class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
|
| MemberElement element = _element;
|
| MemberTypeInformation callee =
|
| inferrer.types.getInferredTypeOfMember(element);
|
| - callee.removeCall(caller, call);
|
| + if (caller.isLocal) {
|
| + callee.removeCallFromLocalFunction(caller, call);
|
| + } else {
|
| + callee.removeCallFromMember(caller, call);
|
| + }
|
| callee.removeUser(this);
|
| inferrer.updateParameterAssignments(
|
| this, element, arguments, selector, typeMask,
|
| @@ -1137,14 +1230,22 @@ class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
|
|
|
| void giveUp(InferrerEngine inferrer, {bool clearAssignments: true}) {
|
| if (!abandonInferencing) {
|
| - inferrer.updateSelectorInTree(caller, call, selector, mask);
|
| + if (caller.isLocal) {
|
| + inferrer.updateSelectorInLocalFunction(caller, call, selector, mask);
|
| + } else {
|
| + inferrer.updateSelectorInMember(caller, call, selector, mask);
|
| + }
|
| Iterable<MemberEntity> oldTargets = targets;
|
| targets = inferrer.closedWorld.locateMembers(selector, mask);
|
| for (MemberElement element in targets) {
|
| if (!oldTargets.contains(element)) {
|
| MemberTypeInformation callee =
|
| inferrer.types.getInferredTypeOfMember(element);
|
| - callee.addCall(caller, call);
|
| + if (caller.isLocal) {
|
| + callee.addCallFromLocalFunction(caller, call);
|
| + } else {
|
| + callee.addCallFromMember(caller, call);
|
| + }
|
| inferrer.updateParameterAssignments(
|
| this, element, arguments, selector, mask,
|
| remove: false, addToQueue: true);
|
| @@ -1694,18 +1795,29 @@ class PhiElementTypeInformation extends TypeInformation {
|
| class ClosureTypeInformation extends TypeInformation
|
| with ApplyableTypeInformation {
|
| final ast.Node node;
|
| - final Element element;
|
| + final Element _element;
|
|
|
| - ClosureTypeInformation(MemberTypeInformation context, this.node, this.element)
|
| + ClosureTypeInformation(
|
| + MemberTypeInformation context, ast.Node node, MethodElement element)
|
| + : this._internal(context, node, element);
|
| +
|
| + ClosureTypeInformation._internal(
|
| + MemberTypeInformation context, this.node, this._element)
|
| : super(context);
|
|
|
| + // TODO(johnniwinther): Type this as `FunctionEntity` when
|
| + // 'LocalFunctionElement.callMethod' is used as key for
|
| + Entity get closure => _element;
|
| +
|
| TypeMask computeType(InferrerEngine inferrer) => safeType(inferrer);
|
|
|
| TypeMask safeType(InferrerEngine inferrer) {
|
| return inferrer.types.functionType.type;
|
| }
|
|
|
| - String toString() => 'Closure $element';
|
| + String get debugName => '$closure';
|
| +
|
| + String toString() => 'Closure $_element';
|
|
|
| accept(TypeInformationVisitor visitor) {
|
| return visitor.visitClosureTypeInformation(this);
|
| @@ -1714,6 +1826,21 @@ class ClosureTypeInformation extends TypeInformation
|
| bool hasStableType(InferrerEngine inferrer) {
|
| return false;
|
| }
|
| +
|
| + String getInferredSignature(TypeSystem types) {
|
| + return types.getInferredSignatureOfMethod(_element);
|
| + }
|
| +}
|
| +
|
| +@deprecated
|
| +class LocalFunctionClosureTypeInformation extends ClosureTypeInformation {
|
| + LocalFunctionClosureTypeInformation(MemberTypeInformation context,
|
| + ast.Node node, LocalFunctionElement element)
|
| + : super._internal(context, node, element);
|
| +
|
| + String getInferredSignature(TypeSystem types) {
|
| + return types.getInferredSignatureOfLocalFunction(_element);
|
| + }
|
| }
|
|
|
| /**
|
|
|