Index: pkg/compiler/lib/src/ssa/builder.dart |
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart |
index 22ef5e1cbb376f88a58e1076a896391c63b95481..ef146154006dfab1e48fbdab30c4641679eba80e 100644 |
--- a/pkg/compiler/lib/src/ssa/builder.dart |
+++ b/pkg/compiler/lib/src/ssa/builder.dart |
@@ -7150,21 +7150,64 @@ class SsaBuilder extends ast.Visitor |
FunctionSignature targetSignature = targetConstructor.functionSignature; |
FunctionSignature redirectingSignature = |
redirectingConstructor.functionSignature; |
- redirectingSignature.forEachRequiredParameter((ParameterElement element) { |
- inputs.add(localsHandler.readLocal(element)); |
- }); |
+ |
+ List<Element> targetRequireds = targetSignature.requiredParameters; |
+ List<Element> redirectingRequireds |
+ = redirectingSignature.requiredParameters; |
+ |
List<Element> targetOptionals = |
targetSignature.orderedOptionalParameters; |
List<Element> redirectingOptionals = |
redirectingSignature.orderedOptionalParameters; |
- int i = 0; |
- for (; i < redirectingOptionals.length; i++) { |
- ParameterElement parameter = redirectingOptionals[i]; |
+ |
+ // TODO(25579): This code can do the wrong thing redirecting constructor and |
+ // the target do not correspond. It is correct if there is no |
+ // warning. Ideally the redirecting constructor and the target would be the |
+ // same function. |
+ |
+ void loadLocal(ParameterElement parameter) { |
inputs.add(localsHandler.readLocal(parameter)); |
} |
- for (; i < targetOptionals.length; i++) { |
- inputs.add(handleConstantForOptionalParameter(targetOptionals[i])); |
+ void loadPosition(int position, ParameterElement optionalParameter) { |
+ if (position < redirectingRequireds.length) { |
+ loadLocal(redirectingRequireds[position]); |
+ } else if (position < redirectingSignature.parameterCount && |
+ !redirectingSignature.optionalParametersAreNamed) { |
+ loadLocal(redirectingOptionals[position - redirectingRequireds.length]); |
+ } else if (optionalParameter != null) { |
+ inputs.add(handleConstantForOptionalParameter(optionalParameter)); |
+ } else { |
+ // Wrong. |
+ inputs.add(graph.addConstantNull(compiler)); |
+ } |
+ } |
+ |
+ int position = 0; |
+ |
+ for (ParameterElement targetParameter in targetRequireds) { |
+ loadPosition(position++, null); |
} |
+ |
+ if (targetOptionals.isNotEmpty) { |
+ if (targetSignature.optionalParametersAreNamed) { |
+ for (ParameterElement parameter in targetOptionals) { |
+ ParameterElement redirectingParameter = |
+ redirectingOptionals.firstWhere( |
+ (p) => p.name == parameter.name, |
+ orElse: () => null); |
+ if (redirectingParameter == null) { |
+ inputs.add(handleConstantForOptionalParameter(parameter)); |
+ } else { |
+ inputs.add(localsHandler.readLocal(redirectingParameter)); |
+ } |
+ } |
+ } else { |
+ for (ParameterElement parameter in targetOptionals) { |
+ loadPosition(position++, parameter); |
+ } |
+ } |
+ } |
+ |
ClassElement targetClass = targetConstructor.enclosingClass; |
if (backend.classNeedsRti(targetClass)) { |
ClassElement cls = redirectingConstructor.enclosingClass; |