| 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..fff0b379a9f566126ad8960642af2cf25550bdb5 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,38 @@ 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 (compiler.enableTypeAssertions && type != null &&
|
| + type.containsTypeVariables) {
|
| + if (insideClosure && member.isFactoryConstructor()) {
|
| + // 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));
|
| + }
|
| + // TODO(karlklose): try to get rid of the isField check; there is a bug
|
| + // with type variable use in field initializer (in both modes).
|
| + if (member.isInstanceMember() && !member.isField()) {
|
| + // 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 +469,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 +495,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 +535,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 +709,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();
|
| });
|
|
|
|
|