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 35b227e9862e3c9d690735ce189511ff116007de..520a7c5faf748ae2899afaea54e66e57dfaa66e9 100644 |
--- a/sdk/lib/_internal/compiler/implementation/closure.dart |
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart |
@@ -523,6 +523,12 @@ class ClosureTranslator extends Visitor { |
useLocal(newElement); |
cached.parametersWithSentinel[parameter] = newElement; |
} |
+ } else if (node.isTypeTest) { |
+ DartType type = elements.getType(node.typeAnnotationFromIsCheck); |
+ analyzeType(type); |
+ } else if (node.isTypeCast) { |
+ DartType type = elements.getType(node.arguments.head); |
+ analyzeType(type); |
} |
node.visitChildren(this); |
} |
@@ -541,44 +547,28 @@ class ClosureTranslator extends Visitor { |
visitNewExpression(NewExpression node) { |
DartType type = elements.getType(node); |
+ analyzeType(type); |
+ node.visitChildren(this); |
+ } |
- bool hasTypeVariable(DartType type) { |
- if (type is TypeVariableType) { |
- return true; |
- } else if (type is InterfaceType) { |
- InterfaceType ifcType = type; |
- for (DartType argument in ifcType.typeArguments) { |
- if (hasTypeVariable(argument)) { |
- return true; |
- } |
- } |
- } |
- return false; |
- } |
- |
- void analyzeTypeVariables(DartType type) { |
- if (type is TypeVariableType) { |
- useLocal(type.element); |
- } else if (type is InterfaceType) { |
- InterfaceType ifcType = type; |
- for (DartType argument in ifcType.typeArguments) { |
- analyzeTypeVariables(argument); |
- } |
- } |
- } |
+ void analyzeTypeVariables(DartType type) { |
+ type.forEachTypeVariable((TypeVariableType typeVariable) { |
+ useLocal(typeVariable.element); |
+ }); |
+ } |
+ void analyzeType(DartType type) { |
if (outermostElement.isMember() && |
- compiler.backend.needsRti(outermostElement.getEnclosingClass())) { |
- if (outermostElement.isConstructor() || outermostElement.isField()) { |
+ compiler.backend.classNeedsRti(outermostElement.getEnclosingClass())) { |
+ if (outermostElement.isConstructor() || |
+ outermostElement.isField()) { |
analyzeTypeVariables(type); |
} else if (outermostElement.isInstanceMember()) { |
- if (hasTypeVariable(type)) { |
+ if (type.containsTypeVariables) { |
registerNeedsThis(); |
} |
} |
} |
- |
- node.visitChildren(this); |
} |
// If variables that are declared in the [node] scope are captured and need |
@@ -737,7 +727,7 @@ class ClosureTranslator extends Visitor { |
} |
if (currentElement.isFactoryConstructor() && |
- compiler.backend.needsRti(currentElement.enclosingElement)) { |
+ compiler.backend.classNeedsRti(currentElement.enclosingElement)) { |
// Declare the type parameters in the scope. Generative |
// constructors just use 'this'. |
ClassElement cls = currentElement.enclosingElement; |
@@ -751,6 +741,13 @@ class ClosureTranslator extends Visitor { |
if (element.computeType(compiler).containsTypeVariables) { |
registerNeedsThis(); |
} |
+ // Ensure that closure that need runtime type information has access to |
+ // this of the enclosing class. |
+ if (element is FunctionElement && |
+ closureData.thisElement != null && |
+ compiler.backend.methodNeedsRti(element)) { |
+ registerNeedsThis(); |
+ } |
visitChildren(); |
}); |