Index: pkg/kernel/lib/transformations/closure/converter.dart |
diff --git a/pkg/kernel/lib/transformations/closure/converter.dart b/pkg/kernel/lib/transformations/closure/converter.dart |
index 5ee224172f0006729dda2786a0733ec62dadfdff..713ab38cdc6995e812fabb5dad3932f2fabd491d 100644 |
--- a/pkg/kernel/lib/transformations/closure/converter.dart |
+++ b/pkg/kernel/lib/transformations/closure/converter.dart |
@@ -13,7 +13,6 @@ import '../../ast.dart' |
ClosureCreation, |
Constructor, |
DartType, |
- DynamicType, |
EmptyStatement, |
Expression, |
ExpressionStatement, |
@@ -260,39 +259,12 @@ class ClosureConverter extends Transformer { |
context = context.toNestedContext( |
new VariableAccessor(contextVariable, null, TreeNode.noOffset)); |
- Set<TypeParameter> captured = capturedTypeVariables[currentFunction]; |
- if (captured != null) { |
- typeSubstitution = copyTypeVariables(captured); |
- } else { |
- typeSubstitution = const <TypeParameter, DartType>{}; |
- } |
+ Set<TypeParameter> captured = |
+ capturedTypeVariables[currentFunction] ?? new Set<TypeParameter>(); |
+ typeSubstitution = copyTypeVariables(captured); |
- // TODO(29181): remove replacementTypeSubstitution variable and its usages. |
- // All the type variables used in this function body are replaced with |
- // either dynamic or their bounds. This is to temporarily remove the type |
- // variables from closure conversion. They should be returned after the VM |
- // changes are done to support vectors and closure creation. See #29181. |
- Map<TypeParameter, DartType> replacementTypeSubstitution = |
- <TypeParameter, DartType>{}; |
- for (TypeParameter parameter in typeSubstitution.keys) { |
- replacementTypeSubstitution[parameter] = const DynamicType(); |
- } |
- for (TypeParameter parameter in typeSubstitution.keys) { |
- if (!isObject(parameter.bound)) { |
- replacementTypeSubstitution[parameter] = |
- substitute(parameter.bound, replacementTypeSubstitution); |
- } |
- } |
- typeSubstitution = replacementTypeSubstitution; |
function.transformChildren(this); |
- // TODO(29181): don't replace typeSubstitution with an empty map. |
- // Information about captured type variables is deleted from the closure |
- // class, because the type variables in this function body are already |
- // replaced with either dynamic or their bounds. This change should be |
- // undone after the VM support for vectors and closure creation is |
- // implemented. See #29181. |
- typeSubstitution = <TypeParameter, DartType>{}; |
Expression result = addClosure(function, contextVariable, parent.expression, |
typeSubstitution, enclosingTypeSubstitution); |
currentFunction = enclosingFunction; |
@@ -322,9 +294,7 @@ class ClosureConverter extends Transformer { |
} |
TreeNode visitFunctionExpression(FunctionExpression node) { |
- return saveContext(() { |
- return handleLocalFunction(node.function); |
- }); |
+ return saveContext(() => handleLocalFunction(node.function)); |
} |
/// Add a new procedure to the current library that looks like this: |
@@ -346,6 +316,16 @@ class ClosureConverter extends Transformer { |
Expression accessContext, |
Map<TypeParameter, DartType> substitution, |
Map<TypeParameter, DartType> enclosingTypeSubstitution) { |
+ var fnTypeParams = <TypeParameter>[]; |
+ var fnTypeArgs = <TypeParameterType>[]; |
+ for (TypeParameter t in substitution.keys) { |
+ var fnTypeParam = (substitution[t] as TypeParameterType).parameter; |
+ fnTypeParams.add(fnTypeParam); |
+ fnTypeArgs |
+ .add(substitute(new TypeParameterType(t), enclosingTypeSubstitution)); |
+ } |
+ |
+ function.typeParameters.insertAll(0, fnTypeParams); |
function.positionalParameters.insert(0, contextVariable); |
++function.requiredParameterCount; |
Procedure closedTopLevelFunction = new Procedure( |
@@ -356,21 +336,29 @@ class ClosureConverter extends Transformer { |
fileUri: currentFileUri); |
newLibraryMembers.add(closedTopLevelFunction); |
+ // We need to again make new type parameters for the function's function |
+ // type, and substitute them into the function type's arguments' types. |
+ var closureTypeParams = <TypeParameter>[]; |
+ var closureTypeSubstitutionMap = copyTypeVariables(function.typeParameters); |
+ for (DartType d in closureTypeSubstitutionMap.values) |
+ closureTypeParams.add((d as TypeParameterType).parameter); |
+ |
FunctionType closureType = new FunctionType( |
function.positionalParameters |
.skip(1) |
- .map((VariableDeclaration decl) => decl.type) |
+ .map((VariableDeclaration decl) => |
+ substitute(decl.type, closureTypeSubstitutionMap)) |
.toList(), |
- function.returnType, |
+ substitute(function.returnType, closureTypeSubstitutionMap), |
namedParameters: function.namedParameters |
- .map((VariableDeclaration decl) => |
- new NamedType(decl.name, decl.type)) |
+ .map((VariableDeclaration decl) => new NamedType( |
+ decl.name, substitute(decl.type, closureTypeSubstitutionMap))) |
.toList(), |
- typeParameters: function.typeParameters, |
+ typeParameters: closureTypeParams, |
requiredParameterCount: function.requiredParameterCount - 1); |
return new ClosureCreation( |
- closedTopLevelFunction, accessContext, closureType); |
+ closedTopLevelFunction, accessContext, closureType, fnTypeArgs); |
} |
TreeNode visitProcedure(Procedure node) { |
@@ -664,14 +652,19 @@ class ClosureConverter extends Transformer { |
/// Creates copies of the type variables in [original] and returns a |
/// substitution that can be passed to [substitute] to substitute all uses of |
- /// [original] with their copies. |
+ /// [original] with their copies. Additionally returns a list of new type |
+ /// parameters to prefix to the enclosing function's type parameters and the |
+ /// arguments to be passed for those parameters. |
+ /// |
Map<TypeParameter, DartType> copyTypeVariables( |
Iterable<TypeParameter> original) { |
if (original.isEmpty) return const <TypeParameter, DartType>{}; |
+ |
Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{}; |
for (TypeParameter t in original) { |
substitution[t] = new TypeParameterType(new TypeParameter(t.name)); |
} |
+ |
substitution.forEach((TypeParameter t, DartType copy) { |
if (copy is TypeParameterType) { |
copy.parameter.bound = substitute(t.bound, substitution); |