Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1774)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/closure.dart

Issue 17262003: Fix type variables in closures. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address Nicolas' comments. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library closureToClassMapper; 5 library closureToClassMapper;
6 6
7 import "elements/elements.dart"; 7 import "elements/elements.dart";
8 import "dart2jslib.dart"; 8 import "dart2jslib.dart";
9 import "dart_types.dart"; 9 import "dart_types.dart";
10 import "scanner/scannerlib.dart" show Token; 10 import "scanner/scannerlib.dart" show Token;
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 } 462 }
463 } 463 }
464 } 464 }
465 465
466 visitTypeAnnotation(TypeAnnotation node) { 466 visitTypeAnnotation(TypeAnnotation node) {
467 Element member = currentElement.getEnclosingMember(); 467 Element member = currentElement.getEnclosingMember();
468 DartType type = elements.getType(node); 468 DartType type = elements.getType(node);
469 // TODO(karlklose,johnniwinther): if the type is null, the annotation is 469 // TODO(karlklose,johnniwinther): if the type is null, the annotation is
470 // from a parameter which has been analyzed before the method has been 470 // from a parameter which has been analyzed before the method has been
471 // resolved and the result has been thrown away. 471 // resolved and the result has been thrown away.
472 if (compiler.enableTypeAssertions && type != null && 472 if (type != null && type.containsTypeVariables) {
473 type.containsTypeVariables) { 473 // TODO(karlklose): try to get rid of the isField check; there is a bug
474 if (insideClosure && member.isFactoryConstructor()) { 474 // with type variable use in field initializer (in both modes).
ngeoffray 2013/06/18 11:14:51 use -> used Could you file a bug? Do you have a f
karlklose 2013/06/19 12:17:27 In fact it is not really a bug, we have to special
475 if (!member.isField()) {
476 // In checked mode, using a type variable in a type annotation may lead
477 // to a runtime type check that needs to access the type argument and
478 // therefore the closure needs a this-element.
479 registerNeedsThis();
ngeoffray 2013/06/18 11:14:51 Thinking more about it, it looks my previous comme
karlklose 2013/06/19 12:17:27 Reverted it back.
480 }
481 if (compiler.enableTypeAssertions && insideClosure &&
482 member.isFactoryConstructor()) {
475 // This is a closure in a factory constructor. Since there is no 483 // This is a closure in a factory constructor. Since there is no
476 // [:this:], we have to mark the type arguments as free variables to 484 // [:this:], we have to mark the type arguments as free variables to
477 // capture them in the closure. 485 // capture them in the closure.
478 type.forEachTypeVariable((variable) => useLocal(variable.element)); 486 type.forEachTypeVariable((variable) => useLocal(variable.element));
479 } 487 }
480 // TODO(karlklose): try to get rid of the isField check; there is a bug
481 // with type variable use in field initializer (in both modes).
482 if (member.isInstanceMember() && !member.isField()) {
483 // In checked mode, using a type variable in a type annotation may lead
484 // to a runtime type check that needs to access the type argument and
485 // therefore the closure needs a this-element.
486 registerNeedsThis();
487 }
488 } 488 }
489 } 489 }
490 490
491 visitIdentifier(Identifier node) { 491 visitIdentifier(Identifier node) {
492 if (node.isThis()) { 492 if (node.isThis()) {
493 registerNeedsThis(); 493 registerNeedsThis();
494 } else { 494 } else {
495 Element element = elements[node]; 495 Element element = elements[node];
496 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) { 496 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) {
497 registerNeedsThis(); 497 registerNeedsThis();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 if (Elements.isLocal(element) && 535 if (Elements.isLocal(element) &&
536 element.computeType(compiler).containsTypeVariables) { 536 element.computeType(compiler).containsTypeVariables) {
537 registerNeedsThis(); 537 registerNeedsThis();
538 } 538 }
539 super.visitSendSet(node); 539 super.visitSendSet(node);
540 } 540 }
541 541
542 visitNewExpression(NewExpression node) { 542 visitNewExpression(NewExpression node) {
543 DartType type = elements.getType(node); 543 DartType type = elements.getType(node);
544 544
545 bool hasTypeVariable(DartType type) {
546 if (type is TypeVariableType) {
547 return true;
548 } else if (type is InterfaceType) {
549 InterfaceType ifcType = type;
550 for (DartType argument in ifcType.typeArguments) {
551 if (hasTypeVariable(argument)) {
552 return true;
553 }
554 }
555 }
556 return false;
557 }
558
559 void analyzeTypeVariables(DartType type) { 545 void analyzeTypeVariables(DartType type) {
560 if (type is TypeVariableType) { 546 if (type is TypeVariableType) {
561 useLocal(type.element); 547 useLocal(type.element);
548 // Field initializers are inlined and access the type variable as
549 // normal parameters.
550 if (!outermostElement.isField()) {
551 registerNeedsThis();
552 }
562 } else if (type is InterfaceType) { 553 } else if (type is InterfaceType) {
563 InterfaceType ifcType = type; 554 InterfaceType ifcType = type;
564 for (DartType argument in ifcType.typeArguments) { 555 for (DartType argument in ifcType.typeArguments) {
565 analyzeTypeVariables(argument); 556 analyzeTypeVariables(argument);
566 } 557 }
567 } 558 }
568 } 559 }
569 560
570 if (outermostElement.isMember() && 561 if (outermostElement.isMember() &&
571 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { 562 compiler.backend.needsRti(outermostElement.getEnclosingClass())) {
572 if (outermostElement.isConstructor() || outermostElement.isField()) { 563 if (outermostElement.isConstructor() || outermostElement.isField()) {
573 analyzeTypeVariables(type); 564 analyzeTypeVariables(type);
574 } else if (outermostElement.isInstanceMember()) { 565 } else if (outermostElement.isInstanceMember()) {
575 if (hasTypeVariable(type)) { 566 if (type.containsTypeVariables) {
576 registerNeedsThis(); 567 registerNeedsThis();
577 } 568 }
578 } 569 }
579 } 570 }
580 571
581 node.visitChildren(this); 572 node.visitChildren(this);
582 } 573 }
583 574
584 // If variables that are declared in the [node] scope are captured and need 575 // If variables that are declared in the [node] scope are captured and need
585 // to be boxed create a box-element and update the [capturingScopes] in the 576 // to be boxed create a box-element and update the [capturingScopes] in the
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 } 793 }
803 794
804 visitTryStatement(TryStatement node) { 795 visitTryStatement(TryStatement node) {
805 // TODO(ngeoffray): implement finer grain state. 796 // TODO(ngeoffray): implement finer grain state.
806 bool oldInTryStatement = inTryStatement; 797 bool oldInTryStatement = inTryStatement;
807 inTryStatement = true; 798 inTryStatement = true;
808 node.visitChildren(this); 799 node.visitChildren(this);
809 inTryStatement = oldInTryStatement; 800 inTryStatement = oldInTryStatement;
810 } 801 }
811 } 802 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698