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

Side by Side Diff: lib/type_checker.dart

Issue 2473523004: Fix expected return type in async functions (Closed)
Patch Set: Also handle yield* Created 4 years, 1 month 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
« no previous file with comments | « no previous file | lib/type_environment.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 } 151 }
152 152
153 visitConstructor(Constructor node) { 153 visitConstructor(Constructor node) {
154 environment.returnType = null; 154 environment.returnType = null;
155 environment.yieldType = null; 155 environment.yieldType = null;
156 node.initializers.forEach(visitInitializer); 156 node.initializers.forEach(visitInitializer);
157 handleFunctionNode(node.function); 157 handleFunctionNode(node.function);
158 } 158 }
159 159
160 visitProcedure(Procedure node) { 160 visitProcedure(Procedure node) {
161 environment.returnType = node.function.returnType; 161 environment.returnType = _getInternalReturnType(node.function);
162 environment.yieldType = _getYieldType(node.function); 162 environment.yieldType = _getYieldType(node.function);
163 handleFunctionNode(node.function); 163 handleFunctionNode(node.function);
164 } 164 }
165 165
166 void handleFunctionNode(FunctionNode node) { 166 void handleFunctionNode(FunctionNode node) {
167 var oldAsyncMarker = environment.currentAsyncMarker;
168 environment.currentAsyncMarker = node.asyncMarker;
167 node.positionalParameters 169 node.positionalParameters
168 .skip(node.requiredParameterCount) 170 .skip(node.requiredParameterCount)
169 .forEach(handleOptionalParameter); 171 .forEach(handleOptionalParameter);
170 node.namedParameters.forEach(handleOptionalParameter); 172 node.namedParameters.forEach(handleOptionalParameter);
171 if (node.body != null) { 173 if (node.body != null) {
172 visitStatement(node.body); 174 visitStatement(node.body);
173 } 175 }
176 environment.currentAsyncMarker = oldAsyncMarker;
174 } 177 }
175 178
176 void handleNestedFunctionNode(FunctionNode node) { 179 void handleNestedFunctionNode(FunctionNode node) {
177 var oldReturn = environment.returnType; 180 var oldReturn = environment.returnType;
178 var oldYield = environment.yieldType; 181 var oldYield = environment.yieldType;
179 environment.returnType = node.returnType; 182 environment.returnType = _getInternalReturnType(node);
180 environment.yieldType = _getYieldType(node); 183 environment.yieldType = _getYieldType(node);
181 handleFunctionNode(node); 184 handleFunctionNode(node);
182 environment.returnType = oldReturn; 185 environment.returnType = oldReturn;
183 environment.yieldType = oldYield; 186 environment.yieldType = oldYield;
184 } 187 }
185 188
186 void handleOptionalParameter(VariableDeclaration parameter) { 189 void handleOptionalParameter(VariableDeclaration parameter) {
187 if (parameter.initializer != null) { 190 if (parameter.initializer != null) {
188 checkAssignableExpression(parameter.initializer, parameter.type); 191 checkAssignableExpression(parameter.initializer, parameter.type);
189 } 192 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 } 271 }
269 } 272 }
270 if (!found) { 273 if (!found) {
271 fail(argument.value, 'Unexpected named parameter: ${argument.name}'); 274 fail(argument.value, 'Unexpected named parameter: ${argument.name}');
272 return const BottomType(); 275 return const BottomType();
273 } 276 }
274 } 277 }
275 return substitution.substituteType(function.returnType); 278 return substitution.substituteType(function.returnType);
276 } 279 }
277 280
281 DartType _getInternalReturnType(FunctionNode function) {
282 switch (function.asyncMarker) {
283 case AsyncMarker.Sync:
284 return function.returnType;
285
286 case AsyncMarker.Async:
287 Class container = coreTypes.futureClass;
288 DartType returnType = function.returnType;
289 if (returnType is InterfaceType && returnType.classNode == container) {
290 return returnType.typeArguments.single;
291 }
292 return const DynamicType();
293
294 case AsyncMarker.SyncStar:
295 case AsyncMarker.AsyncStar:
296 case AsyncMarker.SyncYielding:
297 return null;
298
299 default:
300 throw 'Unexpected async marker: ${function.asyncMarker}';
301 }
302 }
303
278 DartType _getYieldType(FunctionNode function) { 304 DartType _getYieldType(FunctionNode function) {
279 switch (function.asyncMarker) { 305 switch (function.asyncMarker) {
280 case AsyncMarker.Sync: 306 case AsyncMarker.Sync:
281 case AsyncMarker.Async: 307 case AsyncMarker.Async:
282 return null; 308 return null;
283 309
284 case AsyncMarker.SyncStar: 310 case AsyncMarker.SyncStar:
285 case AsyncMarker.AsyncStar: 311 case AsyncMarker.AsyncStar:
286 Class container = function.asyncMarker == AsyncMarker.SyncStar 312 Class container = function.asyncMarker == AsyncMarker.SyncStar
287 ? coreTypes.iterableClass 313 ? coreTypes.iterableClass
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 visitLabeledStatement(LabeledStatement node) { 755 visitLabeledStatement(LabeledStatement node) {
730 visitStatement(node.body); 756 visitStatement(node.body);
731 } 757 }
732 758
733 @override 759 @override
734 visitReturnStatement(ReturnStatement node) { 760 visitReturnStatement(ReturnStatement node) {
735 if (node.expression != null) { 761 if (node.expression != null) {
736 if (environment.returnType == null) { 762 if (environment.returnType == null) {
737 fail(node, 'Return of a value from void method'); 763 fail(node, 'Return of a value from void method');
738 } else { 764 } else {
739 checkAssignableExpression(node.expression, environment.returnType); 765 var type = visitExpression(node.expression);
766 if (environment.currentAsyncMarker == AsyncMarker.Async) {
767 type = environment.unfutureType(type);
768 }
769 checkAssignable(node.expression, type, environment.returnType);
740 } 770 }
741 } 771 }
742 } 772 }
743 773
744 @override 774 @override
745 visitSwitchStatement(SwitchStatement node) { 775 visitSwitchStatement(SwitchStatement node) {
746 visitExpression(node.expression); 776 visitExpression(node.expression);
747 for (var switchCase in node.cases) { 777 for (var switchCase in node.cases) {
748 switchCase.expressions.forEach(visitExpression); 778 switchCase.expressions.forEach(visitExpression);
749 visitStatement(switchCase.body); 779 visitStatement(switchCase.body);
(...skipping 22 matching lines...) Expand all
772 } 802 }
773 803
774 @override 804 @override
775 visitWhileStatement(WhileStatement node) { 805 visitWhileStatement(WhileStatement node) {
776 checkAssignableExpression(node.condition, environment.boolType); 806 checkAssignableExpression(node.condition, environment.boolType);
777 visitStatement(node.body); 807 visitStatement(node.body);
778 } 808 }
779 809
780 @override 810 @override
781 visitYieldStatement(YieldStatement node) { 811 visitYieldStatement(YieldStatement node) {
782 checkAssignableExpression(node.expression, environment.yieldType); 812 if (node.isYieldStar) {
813 Class container = environment.currentAsyncMarker == AsyncMarker.AsyncStar
814 ? coreTypes.streamClass
815 : coreTypes.iterableClass;
816 var type = visitExpression(node.expression);
817 var asContainer = type is InterfaceType
818 ? hierarchy.getTypeAsInstanceOf(type, container)
819 : null;
820 if (asContainer != null) {
821 checkAssignable(node.expression, asContainer.typeArguments[0],
822 environment.yieldType);
823 } else {
824 fail(node.expression, '$type is not an instance of $container');
825 }
826 } else {
827 checkAssignableExpression(node.expression, environment.yieldType);
828 }
783 } 829 }
784 830
785 @override 831 @override
786 visitFieldInitializer(FieldInitializer node) { 832 visitFieldInitializer(FieldInitializer node) {
787 checkAssignableExpression(node.value, node.field.type); 833 checkAssignableExpression(node.value, node.field.type);
788 } 834 }
789 835
790 @override 836 @override
791 visitRedirectingInitializer(RedirectingInitializer node) { 837 visitRedirectingInitializer(RedirectingInitializer node) {
792 handleCall(node.arguments, node.target.function, 838 handleCall(node.arguments, node.target.function,
793 typeParameters: const <TypeParameter>[]); 839 typeParameters: const <TypeParameter>[]);
794 } 840 }
795 841
796 @override 842 @override
797 visitSuperInitializer(SuperInitializer node) { 843 visitSuperInitializer(SuperInitializer node) {
798 handleCall(node.arguments, node.target.function, 844 handleCall(node.arguments, node.target.function,
799 typeParameters: const <TypeParameter>[]); 845 typeParameters: const <TypeParameter>[]);
800 } 846 }
801 847
802 @override 848 @override
803 visitLocalInitializer(LocalInitializer node) { 849 visitLocalInitializer(LocalInitializer node) {
804 visitVariableDeclaration(node.variable); 850 visitVariableDeclaration(node.variable);
805 } 851 }
806 852
807 @override 853 @override
808 visitInvalidInitializer(InvalidInitializer node) {} 854 visitInvalidInitializer(InvalidInitializer node) {}
809 } 855 }
OLDNEW
« no previous file with comments | « no previous file | lib/type_environment.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698