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

Side by Side Diff: pkg/kernel/lib/type_checker.dart

Issue 2619193003: Insert implicit downcasts in kernel strong mode. (Closed)
Patch Set: Add missing status line Created 3 years, 11 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
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 library kernel.type_checker; 4 library kernel.type_checker;
5 5
6 import 'ast.dart'; 6 import 'ast.dart';
7 import 'class_hierarchy.dart'; 7 import 'class_hierarchy.dart';
8 import 'core_types.dart'; 8 import 'core_types.dart';
9 import 'type_algebra.dart'; 9 import 'type_algebra.dart';
10 import 'type_environment.dart'; 10 import 'type_environment.dart';
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 checkAssignable(ownMember, getterType(host, ownMember), 78 checkAssignable(ownMember, getterType(host, ownMember),
79 getterType(host, superMember)); 79 getterType(host, superMember));
80 } 80 }
81 } 81 }
82 82
83 /// Check that [from] is a subtype of [to]. 83 /// Check that [from] is a subtype of [to].
84 /// 84 ///
85 /// [where] is an AST node indicating roughly where the check is required. 85 /// [where] is an AST node indicating roughly where the check is required.
86 void checkAssignable(TreeNode where, DartType from, DartType to); 86 void checkAssignable(TreeNode where, DartType from, DartType to);
87 87
88 /// Checks that [expression], which has type [from], can be assigned to [to].
89 ///
90 /// Should return a downcast if necessary, or [expression] if no cast is
91 /// needed.
92 Expression checkAndDowncastExpression(
93 Expression expression, DartType from, DartType to) {
94 checkAssignable(expression, from, to);
95 return expression;
96 }
97
88 /// Indicates that type checking failed. 98 /// Indicates that type checking failed.
89 void fail(TreeNode where, String message); 99 void fail(TreeNode where, String message);
90 } 100 }
91 101
92 class TypeCheckingVisitor 102 class TypeCheckingVisitor
93 implements 103 implements
94 ExpressionVisitor<DartType>, 104 ExpressionVisitor<DartType>,
95 StatementVisitor<Null>, 105 StatementVisitor<Null>,
96 MemberVisitor<Null>, 106 MemberVisitor<Null>,
97 InitializerVisitor<Null> { 107 InitializerVisitor<Null> {
98 final TypeChecker checker; 108 final TypeChecker checker;
99 final TypeEnvironment environment; 109 final TypeEnvironment environment;
100 110
101 CoreTypes get coreTypes => environment.coreTypes; 111 CoreTypes get coreTypes => environment.coreTypes;
102 ClassHierarchy get hierarchy => environment.hierarchy; 112 ClassHierarchy get hierarchy => environment.hierarchy;
103 Class get currentClass => environment.thisType.classNode; 113 Class get currentClass => environment.thisType.classNode;
104 114
105 TypeCheckingVisitor(this.checker, this.environment); 115 TypeCheckingVisitor(this.checker, this.environment);
106 116
107 void checkAssignable(TreeNode where, DartType from, DartType to) { 117 void checkAssignable(TreeNode where, DartType from, DartType to) {
108 checker.checkAssignable(where, from, to); 118 checker.checkAssignable(where, from, to);
109 } 119 }
110 120
111 void checkAssignableExpression(Expression from, DartType to) { 121 Expression checkAndDowncastExpression(Expression from, DartType to) {
112 checker.checkAssignable(from, visitExpression(from), to); 122 var parent = from.parent;
123 var type = visitExpression(from);
124 var result = checker.checkAndDowncastExpression(from, type, to);
125 result.parent = parent;
126 return result;
127 }
128
129 void checkExpressionNoDowncast(Expression expression, DartType to) {
130 checkAssignable(expression, visitExpression(expression), to);
113 } 131 }
114 132
115 void fail(TreeNode node, String message) { 133 void fail(TreeNode node, String message) {
116 checker.fail(node, message); 134 checker.fail(node, message);
117 } 135 }
118 136
119 DartType visitExpression(Expression node) => node.accept(this); 137 DartType visitExpression(Expression node) => node.accept(this);
120 138
121 void visitStatement(Statement node) { 139 void visitStatement(Statement node) {
122 node.accept(this); 140 node.accept(this);
(...skipping 16 matching lines...) Expand all
139 defaultStatement(Statement node) { 157 defaultStatement(Statement node) {
140 throw 'Unexpected statement ${node.runtimeType}'; 158 throw 'Unexpected statement ${node.runtimeType}';
141 } 159 }
142 160
143 defaultInitializer(Initializer node) { 161 defaultInitializer(Initializer node) {
144 throw 'Unexpected initializer ${node.runtimeType}'; 162 throw 'Unexpected initializer ${node.runtimeType}';
145 } 163 }
146 164
147 visitField(Field node) { 165 visitField(Field node) {
148 if (node.initializer != null) { 166 if (node.initializer != null) {
149 checkAssignableExpression(node.initializer, node.type); 167 node.initializer =
168 checkAndDowncastExpression(node.initializer, node.type);
150 } 169 }
151 } 170 }
152 171
153 visitConstructor(Constructor node) { 172 visitConstructor(Constructor node) {
154 environment.returnType = null; 173 environment.returnType = null;
155 environment.yieldType = null; 174 environment.yieldType = null;
156 node.initializers.forEach(visitInitializer); 175 node.initializers.forEach(visitInitializer);
157 handleFunctionNode(node.function); 176 handleFunctionNode(node.function);
158 } 177 }
159 178
(...skipping 21 matching lines...) Expand all
181 var oldYield = environment.yieldType; 200 var oldYield = environment.yieldType;
182 environment.returnType = _getInternalReturnType(node); 201 environment.returnType = _getInternalReturnType(node);
183 environment.yieldType = _getYieldType(node); 202 environment.yieldType = _getYieldType(node);
184 handleFunctionNode(node); 203 handleFunctionNode(node);
185 environment.returnType = oldReturn; 204 environment.returnType = oldReturn;
186 environment.yieldType = oldYield; 205 environment.yieldType = oldYield;
187 } 206 }
188 207
189 void handleOptionalParameter(VariableDeclaration parameter) { 208 void handleOptionalParameter(VariableDeclaration parameter) {
190 if (parameter.initializer != null) { 209 if (parameter.initializer != null) {
191 checkAssignableExpression(parameter.initializer, parameter.type); 210 // Default parameter values cannot be downcast.
211 checkExpressionNoDowncast(parameter.initializer, parameter.type);
192 } 212 }
193 } 213 }
194 214
195 Substitution getReceiverType( 215 Substitution getReceiverType(
196 TreeNode access, Expression receiver, Member member) { 216 TreeNode access, Expression receiver, Member member) {
197 var type = visitExpression(receiver); 217 var type = visitExpression(receiver);
198 Class superclass = member.enclosingClass; 218 Class superclass = member.enclosingClass;
199 if (superclass.supertype == null) { 219 if (superclass.supertype == null) {
200 return Substitution.empty; // Members on Object are always accessible. 220 return Substitution.empty; // Members on Object are always accessible.
201 } 221 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 var substitution = Substitution.combine(receiver, instantiation); 268 var substitution = Substitution.combine(receiver, instantiation);
249 for (int i = 0; i < typeParameters.length; ++i) { 269 for (int i = 0; i < typeParameters.length; ++i) {
250 var argument = arguments.types[i]; 270 var argument = arguments.types[i];
251 var bound = substitution.substituteType(typeParameters[i].bound); 271 var bound = substitution.substituteType(typeParameters[i].bound);
252 checkAssignable(arguments, argument, bound); 272 checkAssignable(arguments, argument, bound);
253 } 273 }
254 for (int i = 0; i < arguments.positional.length; ++i) { 274 for (int i = 0; i < arguments.positional.length; ++i) {
255 var expectedType = substitution.substituteType( 275 var expectedType = substitution.substituteType(
256 function.positionalParameters[i].type, 276 function.positionalParameters[i].type,
257 contravariant: true); 277 contravariant: true);
258 checkAssignableExpression(arguments.positional[i], expectedType); 278 arguments.positional[i] =
279 checkAndDowncastExpression(arguments.positional[i], expectedType);
259 } 280 }
260 for (int i = 0; i < arguments.named.length; ++i) { 281 for (int i = 0; i < arguments.named.length; ++i) {
261 var argument = arguments.named[i]; 282 var argument = arguments.named[i];
262 bool found = false; 283 bool found = false;
263 for (int j = 0; j < function.namedParameters.length; ++j) { 284 for (int j = 0; j < function.namedParameters.length; ++j) {
264 if (argument.name == function.namedParameters[j].name) { 285 if (argument.name == function.namedParameters[j].name) {
265 var expectedType = substitution.substituteType( 286 var expectedType = substitution.substituteType(
266 function.namedParameters[j].type, 287 function.namedParameters[j].type,
267 contravariant: true); 288 contravariant: true);
268 checkAssignableExpression(argument.value, expectedType); 289 argument.value =
290 checkAndDowncastExpression(argument.value, expectedType);
269 found = true; 291 found = true;
270 break; 292 break;
271 } 293 }
272 } 294 }
273 if (!found) { 295 if (!found) {
274 fail(argument.value, 'Unexpected named parameter: ${argument.name}'); 296 fail(argument.value, 'Unexpected named parameter: ${argument.name}');
275 return const BottomType(); 297 return const BottomType();
276 } 298 }
277 } 299 }
278 return substitution.substituteType(function.returnType); 300 return substitution.substituteType(function.returnType);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 return environment.unfutureType(visitExpression(node.operand)); 359 return environment.unfutureType(visitExpression(node.operand));
338 } 360 }
339 361
340 @override 362 @override
341 DartType visitBoolLiteral(BoolLiteral node) { 363 DartType visitBoolLiteral(BoolLiteral node) {
342 return environment.boolType; 364 return environment.boolType;
343 } 365 }
344 366
345 @override 367 @override
346 DartType visitConditionalExpression(ConditionalExpression node) { 368 DartType visitConditionalExpression(ConditionalExpression node) {
347 checkAssignableExpression(node.condition, environment.boolType); 369 node.condition =
348 checkAssignableExpression(node.then, node.staticType); 370 checkAndDowncastExpression(node.condition, environment.boolType);
349 checkAssignableExpression(node.otherwise, node.staticType); 371 node.then = checkAndDowncastExpression(node.then, node.staticType);
372 node.otherwise =
373 checkAndDowncastExpression(node.otherwise, node.staticType);
350 return node.staticType; 374 return node.staticType;
351 } 375 }
352 376
353 @override 377 @override
354 DartType visitConstructorInvocation(ConstructorInvocation node) { 378 DartType visitConstructorInvocation(ConstructorInvocation node) {
355 Constructor target = node.target; 379 Constructor target = node.target;
356 Arguments arguments = node.arguments; 380 Arguments arguments = node.arguments;
357 Class class_ = target.enclosingClass; 381 Class class_ = target.enclosingClass;
358 handleCall(arguments, target.function, 382 handleCall(arguments, target.function,
359 typeParameters: class_.typeParameters); 383 typeParameters: class_.typeParameters);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 DartType visitLet(Let node) { 436 DartType visitLet(Let node) {
413 var value = visitExpression(node.variable.initializer); 437 var value = visitExpression(node.variable.initializer);
414 if (node.variable.type is DynamicType) { 438 if (node.variable.type is DynamicType) {
415 node.variable.type = value; 439 node.variable.type = value;
416 } 440 }
417 return visitExpression(node.body); 441 return visitExpression(node.body);
418 } 442 }
419 443
420 @override 444 @override
421 DartType visitListLiteral(ListLiteral node) { 445 DartType visitListLiteral(ListLiteral node) {
422 for (var item in node.expressions) { 446 for (int i = 0; i < node.expressions.length; ++i) {
423 checkAssignableExpression(item, node.typeArgument); 447 node.expressions[i] =
448 checkAndDowncastExpression(node.expressions[i], node.typeArgument);
424 } 449 }
425 return environment.literalListType(node.typeArgument); 450 return environment.literalListType(node.typeArgument);
426 } 451 }
427 452
428 @override 453 @override
429 DartType visitLogicalExpression(LogicalExpression node) { 454 DartType visitLogicalExpression(LogicalExpression node) {
430 checkAssignableExpression(node.left, environment.boolType); 455 node.left = checkAndDowncastExpression(node.left, environment.boolType);
431 checkAssignableExpression(node.right, environment.boolType); 456 node.right = checkAndDowncastExpression(node.right, environment.boolType);
432 return environment.boolType; 457 return environment.boolType;
433 } 458 }
434 459
435 @override 460 @override
436 DartType visitMapLiteral(MapLiteral node) { 461 DartType visitMapLiteral(MapLiteral node) {
437 for (var entry in node.entries) { 462 for (var entry in node.entries) {
438 checkAssignableExpression(entry.key, node.keyType); 463 entry.key = checkAndDowncastExpression(entry.key, node.keyType);
439 checkAssignableExpression(entry.value, node.valueType); 464 entry.value = checkAndDowncastExpression(entry.value, node.valueType);
440 } 465 }
441 return environment.literalMapType(node.keyType, node.valueType); 466 return environment.literalMapType(node.keyType, node.valueType);
442 } 467 }
443 468
444 DartType handleDynamicCall(DartType receiver, Arguments arguments) { 469 DartType handleDynamicCall(DartType receiver, Arguments arguments) {
445 arguments.positional.forEach(visitExpression); 470 arguments.positional.forEach(visitExpression);
446 arguments.named.forEach((NamedExpression n) => visitExpression(n.value)); 471 arguments.named.forEach((NamedExpression n) => visitExpression(n.value));
447 return const DynamicType(); 472 return const DynamicType();
448 } 473 }
449 474
(...skipping 10 matching lines...) Expand all
460 if (function.typeParameters.length != arguments.types.length) { 485 if (function.typeParameters.length != arguments.types.length) {
461 fail(access, 'Wrong number of type arguments'); 486 fail(access, 'Wrong number of type arguments');
462 return const BottomType(); 487 return const BottomType();
463 } 488 }
464 var instantiation = 489 var instantiation =
465 Substitution.fromPairs(function.typeParameters, arguments.types); 490 Substitution.fromPairs(function.typeParameters, arguments.types);
466 for (int i = 0; i < arguments.positional.length; ++i) { 491 for (int i = 0; i < arguments.positional.length; ++i) {
467 var expectedType = instantiation.substituteType( 492 var expectedType = instantiation.substituteType(
468 function.positionalParameters[i], 493 function.positionalParameters[i],
469 contravariant: true); 494 contravariant: true);
470 checkAssignableExpression(arguments.positional[i], expectedType); 495 arguments.positional[i] =
496 checkAndDowncastExpression(arguments.positional[i], expectedType);
471 } 497 }
472 for (int i = 0; i < arguments.named.length; ++i) { 498 for (int i = 0; i < arguments.named.length; ++i) {
473 var argument = arguments.named[i]; 499 var argument = arguments.named[i];
474 bool found = false; 500 bool found = false;
475 for (int j = 0; j < function.namedParameters.length; ++j) { 501 for (int j = 0; j < function.namedParameters.length; ++j) {
476 if (argument.name == function.namedParameters[j].name) { 502 if (argument.name == function.namedParameters[j].name) {
477 var expectedType = instantiation.substituteType( 503 var expectedType = instantiation.substituteType(
478 function.namedParameters[j].type, 504 function.namedParameters[j].type,
479 contravariant: true); 505 contravariant: true);
480 checkAssignableExpression(argument.value, expectedType); 506 argument.value =
507 checkAndDowncastExpression(argument.value, expectedType);
481 found = true; 508 found = true;
482 break; 509 break;
483 } 510 }
484 } 511 }
485 if (!found) { 512 if (!found) {
486 fail(argument.value, 'Unexpected named parameter: ${argument.name}'); 513 fail(argument.value, 'Unexpected named parameter: ${argument.name}');
487 return const BottomType(); 514 return const BottomType();
488 } 515 }
489 } 516 }
490 return instantiation.substituteType(function.returnType); 517 return instantiation.substituteType(function.returnType);
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 694
668 @override 695 @override
669 visitBreakStatement(BreakStatement node) {} 696 visitBreakStatement(BreakStatement node) {}
670 697
671 @override 698 @override
672 visitContinueSwitchStatement(ContinueSwitchStatement node) {} 699 visitContinueSwitchStatement(ContinueSwitchStatement node) {}
673 700
674 @override 701 @override
675 visitDoStatement(DoStatement node) { 702 visitDoStatement(DoStatement node) {
676 visitStatement(node.body); 703 visitStatement(node.body);
677 checkAssignableExpression(node.condition, environment.boolType); 704 node.condition =
705 checkAndDowncastExpression(node.condition, environment.boolType);
678 } 706 }
679 707
680 @override 708 @override
681 visitEmptyStatement(EmptyStatement node) {} 709 visitEmptyStatement(EmptyStatement node) {}
682 710
683 @override 711 @override
684 visitExpressionStatement(ExpressionStatement node) { 712 visitExpressionStatement(ExpressionStatement node) {
685 visitExpression(node.expression); 713 visitExpression(node.expression);
686 } 714 }
687 715
688 @override 716 @override
689 visitForInStatement(ForInStatement node) { 717 visitForInStatement(ForInStatement node) {
690 var iterable = visitExpression(node.iterable); 718 var iterable = visitExpression(node.iterable);
691 // TODO(asgerf): Store interface targets on for-in loops or desugar them, 719 // TODO(asgerf): Store interface targets on for-in loops or desugar them,
692 // instead of doing the ad-hoc resolution here. 720 // instead of doing the ad-hoc resolution here.
693 if (node.isAsync) { 721 if (node.isAsync) {
694 checkAssignable(node, getStreamElementType(iterable), node.variable.type); 722 checkAssignable(node, getStreamElementType(iterable), node.variable.type);
695 } else { 723 } else {
696 checkAssignable( 724 checkAssignable(
697 node, getIterableElementType(iterable), node.variable.type); 725 node, getIterableElementType(iterable), node.variable.type);
698 } 726 }
699 visitStatement(node.body); 727 visitStatement(node.body);
700 } 728 }
701 729
702 static final Name iteratorName = new Name('iterator'); 730 static final Name iteratorName = new Name('iterator');
703 static final Name nextName = new Name('next'); 731 static final Name currentName = new Name('current');
704 732
705 DartType getIterableElementType(DartType iterable) { 733 DartType getIterableElementType(DartType iterable) {
706 if (iterable is InterfaceType) { 734 if (iterable is InterfaceType) {
707 var iteratorGetter = 735 var iteratorGetter =
708 hierarchy.getInterfaceMember(iterable.classNode, iteratorName); 736 hierarchy.getInterfaceMember(iterable.classNode, iteratorName);
709 if (iteratorGetter == null) return const DynamicType(); 737 if (iteratorGetter == null) return const DynamicType();
738 var castedIterable = hierarchy.getTypeAsInstanceOf(
739 iterable, iteratorGetter.enclosingClass);
710 var iteratorType = Substitution 740 var iteratorType = Substitution
711 .fromInterfaceType(iterable) 741 .fromInterfaceType(castedIterable)
712 .substituteType(iteratorGetter.getterType); 742 .substituteType(iteratorGetter.getterType);
713 if (iteratorType is InterfaceType) { 743 if (iteratorType is InterfaceType) {
714 var nextGetter = 744 var currentGetter =
715 hierarchy.getInterfaceMember(iteratorType.classNode, nextName); 745 hierarchy.getInterfaceMember(iteratorType.classNode, currentName);
716 if (nextGetter == null) return const DynamicType(); 746 if (currentGetter == null) return const DynamicType();
747 var castedIteratorType = hierarchy.getTypeAsInstanceOf(
748 iteratorType, currentGetter.enclosingClass);
717 return Substitution 749 return Substitution
718 .fromInterfaceType(iteratorType) 750 .fromInterfaceType(castedIteratorType)
719 .substituteType(nextGetter.getterType); 751 .substituteType(currentGetter.getterType);
720 } 752 }
721 } 753 }
722 return const DynamicType(); 754 return const DynamicType();
723 } 755 }
724 756
725 DartType getStreamElementType(DartType stream) { 757 DartType getStreamElementType(DartType stream) {
726 if (stream is InterfaceType) { 758 if (stream is InterfaceType) {
727 var asStream = 759 var asStream =
728 hierarchy.getTypeAsInstanceOf(stream, coreTypes.streamClass); 760 hierarchy.getTypeAsInstanceOf(stream, coreTypes.streamClass);
729 if (asStream == null) return const DynamicType(); 761 if (asStream == null) return const DynamicType();
730 return asStream.typeArguments.single; 762 return asStream.typeArguments.single;
731 } 763 }
732 return const DynamicType(); 764 return const DynamicType();
733 } 765 }
734 766
735 @override 767 @override
736 visitForStatement(ForStatement node) { 768 visitForStatement(ForStatement node) {
737 node.variables.forEach(visitVariableDeclaration); 769 node.variables.forEach(visitVariableDeclaration);
738 if (node.condition != null) { 770 if (node.condition != null) {
739 checkAssignableExpression(node.condition, environment.boolType); 771 node.condition =
772 checkAndDowncastExpression(node.condition, environment.boolType);
740 } 773 }
741 node.updates.forEach(visitExpression); 774 node.updates.forEach(visitExpression);
742 visitStatement(node.body); 775 visitStatement(node.body);
743 } 776 }
744 777
745 @override 778 @override
746 visitFunctionDeclaration(FunctionDeclaration node) { 779 visitFunctionDeclaration(FunctionDeclaration node) {
747 handleNestedFunctionNode(node.function); 780 handleNestedFunctionNode(node.function);
748 } 781 }
749 782
750 @override 783 @override
751 visitIfStatement(IfStatement node) { 784 visitIfStatement(IfStatement node) {
752 checkAssignableExpression(node.condition, environment.boolType); 785 node.condition =
786 checkAndDowncastExpression(node.condition, environment.boolType);
753 visitStatement(node.then); 787 visitStatement(node.then);
754 if (node.otherwise != null) { 788 if (node.otherwise != null) {
755 visitStatement(node.otherwise); 789 visitStatement(node.otherwise);
756 } 790 }
757 } 791 }
758 792
759 @override 793 @override
760 visitInvalidStatement(InvalidStatement node) {} 794 visitInvalidStatement(InvalidStatement node) {}
761 795
762 @override 796 @override
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 832
799 @override 833 @override
800 visitTryFinally(TryFinally node) { 834 visitTryFinally(TryFinally node) {
801 visitStatement(node.body); 835 visitStatement(node.body);
802 visitStatement(node.finalizer); 836 visitStatement(node.finalizer);
803 } 837 }
804 838
805 @override 839 @override
806 visitVariableDeclaration(VariableDeclaration node) { 840 visitVariableDeclaration(VariableDeclaration node) {
807 if (node.initializer != null) { 841 if (node.initializer != null) {
808 checkAssignableExpression(node.initializer, node.type); 842 node.initializer =
843 checkAndDowncastExpression(node.initializer, node.type);
809 } 844 }
810 } 845 }
811 846
812 @override 847 @override
813 visitWhileStatement(WhileStatement node) { 848 visitWhileStatement(WhileStatement node) {
814 checkAssignableExpression(node.condition, environment.boolType); 849 node.condition =
850 checkAndDowncastExpression(node.condition, environment.boolType);
815 visitStatement(node.body); 851 visitStatement(node.body);
816 } 852 }
817 853
818 @override 854 @override
819 visitYieldStatement(YieldStatement node) { 855 visitYieldStatement(YieldStatement node) {
820 if (node.isYieldStar) { 856 if (node.isYieldStar) {
821 Class container = environment.currentAsyncMarker == AsyncMarker.AsyncStar 857 Class container = environment.currentAsyncMarker == AsyncMarker.AsyncStar
822 ? coreTypes.streamClass 858 ? coreTypes.streamClass
823 : coreTypes.iterableClass; 859 : coreTypes.iterableClass;
824 var type = visitExpression(node.expression); 860 var type = visitExpression(node.expression);
825 var asContainer = type is InterfaceType 861 var asContainer = type is InterfaceType
826 ? hierarchy.getTypeAsInstanceOf(type, container) 862 ? hierarchy.getTypeAsInstanceOf(type, container)
827 : null; 863 : null;
828 if (asContainer != null) { 864 if (asContainer != null) {
829 checkAssignable(node.expression, asContainer.typeArguments[0], 865 checkAssignable(node.expression, asContainer.typeArguments[0],
830 environment.yieldType); 866 environment.yieldType);
831 } else { 867 } else {
832 fail(node.expression, '$type is not an instance of $container'); 868 fail(node.expression, '$type is not an instance of $container');
833 } 869 }
834 } else { 870 } else {
835 checkAssignableExpression(node.expression, environment.yieldType); 871 node.expression =
872 checkAndDowncastExpression(node.expression, environment.yieldType);
836 } 873 }
837 } 874 }
838 875
839 @override 876 @override
840 visitFieldInitializer(FieldInitializer node) { 877 visitFieldInitializer(FieldInitializer node) {
841 checkAssignableExpression(node.value, node.field.type); 878 node.value = checkAndDowncastExpression(node.value, node.field.type);
842 } 879 }
843 880
844 @override 881 @override
845 visitRedirectingInitializer(RedirectingInitializer node) { 882 visitRedirectingInitializer(RedirectingInitializer node) {
846 handleCall(node.arguments, node.target.function, 883 handleCall(node.arguments, node.target.function,
847 typeParameters: const <TypeParameter>[]); 884 typeParameters: const <TypeParameter>[]);
848 } 885 }
849 886
850 @override 887 @override
851 visitSuperInitializer(SuperInitializer node) { 888 visitSuperInitializer(SuperInitializer node) {
852 handleCall(node.arguments, node.target.function, 889 handleCall(node.arguments, node.target.function,
853 typeParameters: const <TypeParameter>[]); 890 typeParameters: const <TypeParameter>[],
891 receiver: getSuperReceiverType(node.target));
854 } 892 }
855 893
856 @override 894 @override
857 visitLocalInitializer(LocalInitializer node) { 895 visitLocalInitializer(LocalInitializer node) {
858 visitVariableDeclaration(node.variable); 896 visitVariableDeclaration(node.variable);
859 } 897 }
860 898
861 @override 899 @override
862 visitInvalidInitializer(InvalidInitializer node) {} 900 visitInvalidInitializer(InvalidInitializer node) {}
863 } 901 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698