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 61ab9b20fe6c7c7d23c6cd4d8e0aa7670b5921c0..38153903b3c0c0fa57993f5737d1102ec24ad451 100644 |
--- a/sdk/lib/_internal/compiler/implementation/closure.dart |
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart |
@@ -529,6 +529,12 @@ class ClosureTranslator extends Visitor { |
useLocal(newElement); |
cached.parametersWithSentinel[parameter] = newElement; |
} |
+ } else if (node.isTypeTest) { |
+ DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); |
+ analyzeType(type); |
+ } else if (node.isTypeCast) { |
+ DartType type = elements.getType(node.arguments.head); |
+ analyzeType(type); |
} |
node.visitChildren(this); |
} |
@@ -547,26 +553,28 @@ class ClosureTranslator extends Visitor { |
visitNewExpression(NewExpression node) { |
DartType type = elements.getType(node); |
+ analyzeType(type); |
+ node.visitChildren(this); |
+ } |
- void analyzeTypeVariables(DartType type) { |
- if (type is TypeVariableType) { |
- useLocal(type.element); |
- // Field initializers are inlined and access the type variable as |
- // normal parameters. |
- if (!outermostElement.isField()) { |
- registerNeedsThis(); |
- } |
- } 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); |
+ // Field initializers are inlined and access the type variable as |
+ // normal parameters. |
+ if (!outermostElement.isField()) { |
+ registerNeedsThis(); |
} |
- } |
+ }); |
+ } |
+ void analyzeType(DartType type) { |
+ // TODO(johnniwinther): Find out why this can be null. |
+ if (type == null) return; |
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 (type.containsTypeVariables) { |
@@ -574,8 +582,6 @@ class ClosureTranslator extends Visitor { |
} |
} |
} |
- |
- node.visitChildren(this); |
} |
// If variables that are declared in the [node] scope are captured and need |
@@ -734,7 +740,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; |
@@ -743,9 +749,18 @@ class ClosureTranslator extends Visitor { |
}); |
} |
+ DartType type = element.computeType(compiler); |
// Compute the function type and check for type variables in return or |
// parameter types. |
- if (element.computeType(compiler).containsTypeVariables) { |
+ if (type.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 && |
+ type.containsTypeVariables && |
+ compiler.backend.methodNeedsRti(element)) { |
registerNeedsThis(); |
} |