Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |