| 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();
|
| }
|
|
|
|
|