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

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: Revert some changes and support as. 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 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 (compiler.enableTypeAssertions && type != null &&
473 type.containsTypeVariables) { 473 type.containsTypeVariables) {
474 if (insideClosure && member.isFactoryConstructor()) { 474 if (insideClosure && member.isFactoryConstructor()) {
475 // This is a closure in a factory constructor. Since there is no 475 // 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 476 // [:this:], we have to mark the type arguments as free variables to
477 // capture them in the closure. 477 // capture them in the closure.
478 type.forEachTypeVariable((variable) => useLocal(variable.element)); 478 type.forEachTypeVariable((variable) => useLocal(variable.element));
479 } 479 }
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()) { 480 if (member.isInstanceMember() && !member.isField()) {
483 // In checked mode, using a type variable in a type annotation may lead 481 // 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 482 // to a runtime type check that needs to access the type argument and
485 // therefore the closure needs a this-element. 483 // therefore the closure needs a this-element, if it is not a field;
ngeoffray 2013/06/19 20:03:57 not a field -> not declared in a field initializer
karlklose 2013/06/20 10:18:00 Done.
484 // field initatializers are evaluated in a context where the type
485 // arguments are available in locals.
486 registerNeedsThis(); 486 registerNeedsThis();
487 } 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();
498 } 498 }
499 } 499 }
500 node.visitChildren(this); 500 node.visitChildren(this);
501 } 501 }
502 502
503 visitSend(Send node) { 503 visitSend(Send node) {
504 Element element = elements[node]; 504 Element element = elements[node];
505 if (Elements.isLocal(element)) { 505 if (Elements.isLocal(element)) {
506 useLocal(element); 506 useLocal(element);
507 } else if (node.receiver == null && 507 } else if (node.receiver == null &&
508 Elements.isInstanceSend(node, elements)) { 508 Elements.isInstanceSend(node, elements)) {
509 registerNeedsThis(); 509 registerNeedsThis();
510 } else if (node.isSuperCall) { 510 } else if (node.isSuperCall) {
511 registerNeedsThis(); 511 registerNeedsThis();
512 } else if (node.isIsCheck || node.isIsNotCheck || node.isTypeCast) {
513 TypeAnnotation annotation = node.typeAnnotationFromIsCheck;
514 DartType type = elements.getType(annotation);
515 if (type != null && type.containsTypeVariables) {
516 registerNeedsThis();
517 }
512 } else if (node.isParameterCheck) { 518 } else if (node.isParameterCheck) {
513 Element parameter = elements[node.receiver]; 519 Element parameter = elements[node.receiver];
514 FunctionElement enclosing = parameter.enclosingElement; 520 FunctionElement enclosing = parameter.enclosingElement;
515 FunctionExpression function = enclosing.parseNode(compiler); 521 FunctionExpression function = enclosing.parseNode(compiler);
516 ClosureClassMap cached = closureMappingCache[function]; 522 ClosureClassMap cached = closureMappingCache[function];
517 if (!cached.parametersWithSentinel.containsKey(parameter)) { 523 if (!cached.parametersWithSentinel.containsKey(parameter)) {
518 SourceString parameterName = parameter.name; 524 SourceString parameterName = parameter.name;
519 String name = '${parameterName.slowToString()}_check'; 525 String name = '${parameterName.slowToString()}_check';
520 Element newElement = new CheckVariableElement(new SourceString(name), 526 Element newElement = new CheckVariableElement(new SourceString(name),
521 parameter, 527 parameter,
(...skipping 13 matching lines...) Expand all
535 if (Elements.isLocal(element) && 541 if (Elements.isLocal(element) &&
536 element.computeType(compiler).containsTypeVariables) { 542 element.computeType(compiler).containsTypeVariables) {
537 registerNeedsThis(); 543 registerNeedsThis();
538 } 544 }
539 super.visitSendSet(node); 545 super.visitSendSet(node);
540 } 546 }
541 547
542 visitNewExpression(NewExpression node) { 548 visitNewExpression(NewExpression node) {
543 DartType type = elements.getType(node); 549 DartType type = elements.getType(node);
544 550
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) { 551 void analyzeTypeVariables(DartType type) {
560 if (type is TypeVariableType) { 552 if (type is TypeVariableType) {
561 useLocal(type.element); 553 useLocal(type.element);
554 // Field initializers are inlined and access the type variable as
555 // normal parameters.
556 if (!outermostElement.isField()) {
557 registerNeedsThis();
558 }
562 } else if (type is InterfaceType) { 559 } else if (type is InterfaceType) {
563 InterfaceType ifcType = type; 560 InterfaceType ifcType = type;
564 for (DartType argument in ifcType.typeArguments) { 561 for (DartType argument in ifcType.typeArguments) {
565 analyzeTypeVariables(argument); 562 analyzeTypeVariables(argument);
566 } 563 }
567 } 564 }
568 } 565 }
569 566
570 if (outermostElement.isMember() && 567 if (outermostElement.isMember() &&
571 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { 568 compiler.backend.needsRti(outermostElement.getEnclosingClass())) {
572 if (outermostElement.isConstructor() || outermostElement.isField()) { 569 if (outermostElement.isConstructor() || outermostElement.isField()) {
573 analyzeTypeVariables(type); 570 analyzeTypeVariables(type);
574 } else if (outermostElement.isInstanceMember()) { 571 } else if (outermostElement.isInstanceMember()) {
575 if (hasTypeVariable(type)) { 572 if (type.containsTypeVariables) {
576 registerNeedsThis(); 573 registerNeedsThis();
577 } 574 }
578 } 575 }
579 } 576 }
580 577
581 node.visitChildren(this); 578 node.visitChildren(this);
582 } 579 }
583 580
584 // If variables that are declared in the [node] scope are captured and need 581 // 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 582 // 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 } 799 }
803 800
804 visitTryStatement(TryStatement node) { 801 visitTryStatement(TryStatement node) {
805 // TODO(ngeoffray): implement finer grain state. 802 // TODO(ngeoffray): implement finer grain state.
806 bool oldInTryStatement = inTryStatement; 803 bool oldInTryStatement = inTryStatement;
807 inTryStatement = true; 804 inTryStatement = true;
808 node.visitChildren(this); 805 node.visitChildren(this);
809 inTryStatement = oldInTryStatement; 806 inTryStatement = oldInTryStatement;
810 } 807 }
811 } 808 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698