Index: pkg/compiler/lib/src/kernel/element_map_impl.dart |
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart |
index 7d7d048ba0bba10b2a85558c1bf3b6cea018c619..6348d9aea9e5538545e99229e0a3cf6c32b0e1fe 100644 |
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart |
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart |
@@ -5,6 +5,8 @@ |
library dart2js.kernel.element_map; |
import 'package:kernel/ast.dart' as ir; |
+import 'package:kernel/clone.dart'; |
+import 'package:kernel/type_algebra.dart'; |
import '../common.dart'; |
import '../common/names.dart' show Identifiers; |
@@ -619,7 +621,27 @@ class KernelToElementMapImpl extends KernelToElementMapMixin { |
} |
@override |
- FunctionEntity getConstructor(ir.Member node) => _getConstructor(node); |
+ ConstructorEntity getConstructor(ir.Member node) => _getConstructor(node); |
+ |
+ @override |
+ ConstructorEntity getSuperConstructor( |
+ ir.Constructor sourceNode, ir.Member targetNode) { |
+ KConstructor source = getConstructor(sourceNode); |
+ KClass sourceClass = source.enclosingClass; |
+ KConstructor target = getConstructor(targetNode); |
+ KClass targetClass = target.enclosingClass; |
+ KClass superClass = _getSuperType(sourceClass)?.element; |
+ if (superClass == targetClass) { |
+ return target; |
+ } |
+ _KClassEnv env = _classEnvs[superClass.classIndex]; |
+ ir.Member member = env.lookupConstructor(target.name); |
+ if (member != null) { |
+ return getConstructor(member); |
+ } |
+ throw new SpannableAssertionFailure( |
+ source, "Super constructor for $source not found."); |
+ } |
ConstantConstructor _getConstructorConstant(KConstructor constructor) { |
_ConstructorData data = _memberList[constructor.memberIndex]; |
@@ -786,7 +808,54 @@ class _KClassEnv { |
_KClassEnv(this.cls) |
// TODO(johnniwinther): Change this to use a property on [cls] when such |
// is added to kernel. |
- : isUnnamedMixinApplication = cls.name.contains('+'); |
+ : isUnnamedMixinApplication = |
+ cls.name.contains('+') || cls.name.contains('&'); |
+ |
+ /// Copied from 'package:kernel/transformations/mixin_full_resolution.dart'. |
+ ir.Constructor _buildForwardingConstructor( |
+ CloneVisitor cloner, ir.Constructor superclassConstructor) { |
+ var superFunction = superclassConstructor.function; |
+ |
+ // We keep types and default values for the parameters but always mark the |
+ // parameters as final (since we just forward them to the super |
+ // constructor). |
+ ir.VariableDeclaration cloneVariable(ir.VariableDeclaration variable) { |
+ ir.VariableDeclaration clone = cloner.clone(variable); |
+ clone.isFinal = true; |
+ return clone; |
+ } |
+ |
+ // Build a [FunctionNode] which has the same parameters as the one in the |
+ // superclass constructor. |
+ var positionalParameters = |
+ superFunction.positionalParameters.map(cloneVariable).toList(); |
+ var namedParameters = |
+ superFunction.namedParameters.map(cloneVariable).toList(); |
+ var function = new ir.FunctionNode(new ir.EmptyStatement(), |
+ positionalParameters: positionalParameters, |
+ namedParameters: namedParameters, |
+ requiredParameterCount: superFunction.requiredParameterCount, |
+ returnType: const ir.VoidType()); |
+ |
+ // Build a [SuperInitializer] which takes all positional/named parameters |
+ // and forward them to the super class constructor. |
+ var positionalArguments = <ir.Expression>[]; |
+ for (var variable in positionalParameters) { |
+ positionalArguments.add(new ir.VariableGet(variable)); |
+ } |
+ var namedArguments = <ir.NamedExpression>[]; |
+ for (var variable in namedParameters) { |
+ namedArguments.add( |
+ new ir.NamedExpression(variable.name, new ir.VariableGet(variable))); |
+ } |
+ var superInitializer = new ir.SuperInitializer(superclassConstructor, |
+ new ir.Arguments(positionalArguments, named: namedArguments)); |
+ |
+ // Assemble the constructor. |
+ return new ir.Constructor(function, |
+ name: superclassConstructor.name, |
+ initializers: <ir.Initializer>[superInitializer]); |
+ } |
void _ensureMaps() { |
if (_memberMap == null) { |
@@ -826,6 +895,25 @@ class _KClassEnv { |
addMembers(cls.mixedInClass, includeStatic: false); |
} |
addMembers(cls, includeStatic: true); |
+ |
+ if (isUnnamedMixinApplication && _constructorMap.isEmpty) { |
+ // Unnamed mixin applications have no constructors when read from .dill. |
+ // For each generative constructor in the superclass we make a |
+ // corresponding forwarding constructor in the subclass. |
+ // |
+ // This code is copied from |
+ // 'package:kernel/transformations/mixin_full_resolution.dart' |
+ var superclassSubstitution = getSubstitutionMap(cls.supertype); |
+ var superclassCloner = |
+ new CloneVisitor(typeSubstitution: superclassSubstitution); |
+ for (var superclassConstructor in cls.superclass.constructors) { |
+ var forwardingConstructor = _buildForwardingConstructor( |
+ superclassCloner, superclassConstructor); |
+ cls.addMember(forwardingConstructor); |
+ _constructorMap[forwardingConstructor.name.name] = |
+ forwardingConstructor; |
+ } |
+ } |
} |
} |