| Index: pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
|
| diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
|
| index f897876e0bb32c6b0eeb095ef6a318c7b0e9ec8a..f9608ba026ba3a0204d7efe31e8b7b889a6198db 100644
|
| --- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
|
| +++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
|
| @@ -413,6 +413,9 @@ class SimpleTypeInferrerVisitor<T>
|
| FunctionSignature signature = function.functionSignature;
|
| signature.forEachOptionalParameter((ParameterElement element) {
|
| ast.Expression defaultValue = element.initializer;
|
| + // TODO(25566): The default value of a parameter of a redirecting factory
|
| + // constructor comes from the corresponding parameter of the target.
|
| +
|
| // If this is a default value from a different context (because
|
| // the current function is synthetic, e.g., a constructor from
|
| // a mixin application), we have to start a new inferrer visitor
|
| @@ -1482,54 +1485,50 @@ class SimpleTypeInferrerVisitor<T>
|
| return super.handleTypeLiteralInvoke(arguments);
|
| }
|
|
|
| - /// Handle constructor invocation of [element].
|
| - T handleConstructorSend(ast.Send node, ConstructorElement element) {
|
| + /// Handle constructor invocation of [constructor].
|
| + T handleConstructorSend(ast.Send node, ConstructorElement constructor) {
|
| + ConstructorElement target = constructor.implementation;
|
| ArgumentsTypes arguments = analyzeArguments(node.arguments);
|
| if (visitingInitializers) {
|
| if (ast.Initializers.isConstructorRedirect(node)) {
|
| isConstructorRedirect = true;
|
| } else if (ast.Initializers.isSuperConstructorCall(node)) {
|
| seenSuperConstructorCall = true;
|
| - analyzeSuperConstructorCall(element, arguments);
|
| + analyzeSuperConstructorCall(constructor, arguments);
|
| }
|
| }
|
| - // If we are looking at a new expression on a forwarding factory,
|
| - // we have to forward the call to the effective target of the
|
| - // factory.
|
| - if (element.isFactoryConstructor) {
|
| - // TODO(herhut): Remove the while loop once effectiveTarget forwards to
|
| - // patches.
|
| - while (element.isFactoryConstructor) {
|
| - ConstructorElement constructor = element;
|
| - if (!constructor.isRedirectingFactory) break;
|
| - element = constructor.effectiveTarget.implementation;
|
| - }
|
| + // If we are looking at a new expression on a forwarding factory, we have to
|
| + // forward the call to the effective target of the factory.
|
| + // TODO(herhut): Remove the loop once effectiveTarget forwards to patches.
|
| + while (target.isFactoryConstructor) {
|
| + if (!target.isRedirectingFactory) break;
|
| + target = target.effectiveTarget.implementation;
|
| }
|
| - if (compiler.backend.isForeign(element)) {
|
| - return handleForeignSend(node, element);
|
| + if (compiler.backend.isForeign(target)) {
|
| + return handleForeignSend(node, target);
|
| }
|
| Selector selector = elements.getSelector(node);
|
| TypeMask mask = elements.getTypeMask(node);
|
| // In erroneous code the number of arguments in the selector might not
|
| // match the function element.
|
| // TODO(polux): return nonNullEmpty and check it doesn't break anything
|
| - if (!selector.applies(element, compiler.world) ||
|
| - (mask != null && !mask.canHit(element, selector, compiler.world))) {
|
| + if (!selector.applies(target, compiler.world) ||
|
| + (mask != null && !mask.canHit(target, selector, compiler.world))) {
|
| return types.dynamicType;
|
| }
|
|
|
| - T returnType = handleStaticSend(node, selector, mask, element, arguments);
|
| - if (Elements.isGrowableListConstructorCall(element, node, compiler)) {
|
| + T returnType = handleStaticSend(node, selector, mask, target, arguments);
|
| + if (Elements.isGrowableListConstructorCall(constructor, node, compiler)) {
|
| return inferrer.concreteTypes.putIfAbsent(
|
| node, () => types.allocateList(
|
| types.growableListType, node, outermostElement,
|
| types.nonNullEmpty(), 0));
|
| - } else if (Elements.isFixedListConstructorCall(element, node, compiler)
|
| - || Elements.isFilledListConstructorCall(element, node, compiler)) {
|
| + } else if (Elements.isFixedListConstructorCall(constructor, node, compiler)
|
| + || Elements.isFilledListConstructorCall(constructor, node, compiler)) {
|
|
|
| int length = findLength(node);
|
| T elementType =
|
| - Elements.isFixedListConstructorCall(element, node, compiler)
|
| + Elements.isFixedListConstructorCall(constructor, node, compiler)
|
| ? types.nullType
|
| : arguments.positional[1];
|
|
|
| @@ -1537,15 +1536,14 @@ class SimpleTypeInferrerVisitor<T>
|
| node, () => types.allocateList(
|
| types.fixedListType, node, outermostElement,
|
| elementType, length));
|
| - } else if (Elements.isConstructorOfTypedArraySubclass(element, compiler)) {
|
| + } else if (
|
| + Elements.isConstructorOfTypedArraySubclass(constructor, compiler)) {
|
| int length = findLength(node);
|
| - ConstructorElement constructor = element.implementation;
|
| - constructor = constructor.effectiveTarget;
|
| T elementType = inferrer.returnTypeOfElement(
|
| - constructor.enclosingClass.lookupMember('[]'));
|
| + target.enclosingClass.lookupMember('[]'));
|
| return inferrer.concreteTypes.putIfAbsent(
|
| node, () => types.allocateList(
|
| - types.nonNullExact(constructor.enclosingClass), node,
|
| + types.nonNullExact(target.enclosingClass), node,
|
| outermostElement, elementType, length));
|
| } else {
|
| return returnType;
|
|
|