Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/closure.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart |
| index b9b83e2bb716db19122e95b3bf1800e4a6cf4a11..cf801125763fdc6ca848e5fe293d070ebf92cbdf 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/closure.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/closure.dart |
| @@ -390,11 +390,20 @@ class ClosureTranslator extends Visitor { |
| scopeVariables.add(element); |
| } |
| + void registerNeedsThis() { |
| + if (closureData.thisElement != null) { |
| + useLocal(closureData.thisElement); |
| + } |
| + } |
| + |
| visit(Node node) => node.accept(this); |
| visitNode(Node node) => node.visitChildren(this); |
| visitVariableDefinitions(VariableDefinitions node) { |
| + if (node.type != null) { |
| + visit(node.type); |
| + } |
| for (Link<Node> link = node.definitions.nodes; |
| !link.isEmpty; |
| link = link.tail) { |
| @@ -417,13 +426,37 @@ class ClosureTranslator extends Visitor { |
| } |
| } |
| + visitTypeAnnotation(TypeAnnotation node) { |
| + Element member = currentElement.getEnclosingMember(); |
| + DartType type = elements.getType(node); |
| + // TODO(karlklose,johnniwinther): if the type is null, the annotation is |
| + // from a parameter which has been analyzed before the method has been |
| + // resolved and the result has been thrown away. |
| + if (type != null && type.containsTypeVariables) { |
| + if (member != currentElement && member.isFactoryConstructor() && |
|
ngeoffray
2013/05/17 08:17:45
Instead of member != currentElement, could you use
karlklose
2013/05/17 09:38:34
Done.
|
| + compiler.enableTypeAssertions) { |
| + // This is a closure in a factory constructor. Since there is no |
| + // [:this:], we have to mark the type arguments as free variables to |
| + // capture them in the closure. |
| + type.forEachTypeVariable((variable) => useLocal(variable.element)); |
| + } |
| + if (compiler.enableTypeAssertions && member.isInstanceMember() && |
|
ngeoffray
2013/05/17 08:17:45
You can move enableTypeAssertions in the outer if.
karlklose
2013/05/17 09:38:34
Done.
|
| + !member.isField()) { |
|
ngeoffray
2013/05/17 08:17:45
This isField check looks suspicious. Could you add
karlklose
2013/05/17 09:38:34
Done.
|
| + // In checked mode, using a type variable in a type annotation may lead |
| + // to a runtime type check that needs to access the type argument and |
| + // therefore the closure needs a this-element. |
| + registerNeedsThis(); |
| + } |
| + } |
| + } |
| + |
| visitIdentifier(Identifier node) { |
| if (node.isThis()) { |
| - useLocal(closureData.thisElement); |
| + registerNeedsThis(); |
| } else { |
| Element element = elements[node]; |
| if (element != null && element.kind == ElementKind.TYPE_VARIABLE) { |
| - useLocal(closureData.thisElement); |
| + registerNeedsThis(); |
| } |
| } |
| node.visitChildren(this); |
| @@ -435,9 +468,9 @@ class ClosureTranslator extends Visitor { |
| useLocal(element); |
| } else if (node.receiver == null && |
| Elements.isInstanceSend(node, elements)) { |
| - useLocal(closureData.thisElement); |
| + registerNeedsThis(); |
| } else if (node.isSuperCall) { |
| - useLocal(closureData.thisElement); |
| + registerNeedsThis(); |
| } else if (node.isParameterCheck) { |
| Element parameter = elements[node.receiver]; |
| FunctionElement enclosing = parameter.enclosingElement; |
| @@ -461,6 +494,10 @@ class ClosureTranslator extends Visitor { |
| if (Elements.isLocal(element)) { |
| mutatedVariables.add(element); |
| } |
| + if (Elements.isLocal(element) && |
| + element.computeType(compiler).containsTypeVariables) { |
| + registerNeedsThis(); |
| + } |
| super.visitSendSet(node); |
| } |
| @@ -497,7 +534,9 @@ class ClosureTranslator extends Visitor { |
| if (outermostElement.isConstructor() || outermostElement.isField()) { |
| analyzeTypeVariables(type); |
| } else if (outermostElement.isInstanceMember()) { |
| - if (hasTypeVariable(type)) useLocal(closureData.thisElement); |
| + if (hasTypeVariable(type)) { |
| + registerNeedsThis(); |
| + } |
| } |
| } |
| @@ -669,6 +708,12 @@ class ClosureTranslator extends Visitor { |
| }); |
| } |
| + // Compute the function type and check for type variables in return or |
| + // parameter types. |
| + if (element.computeType(compiler).containsTypeVariables) { |
| + registerNeedsThis(); |
| + } |
| + |
| visitChildren(); |
| }); |