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

Side by Side Diff: runtime/vm/parser.cc

Issue 2057903003: Capture instantiator in async function when required to check result type. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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
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 #include "vm/parser.h" 5 #include "vm/parser.h"
6 #include "vm/flags.h" 6 #include "vm/flags.h"
7 7
8 #ifndef DART_PRECOMPILED_RUNTIME 8 #ifndef DART_PRECOMPILED_RUNTIME
9 9
10 #include "lib/invocation_mirror.h" 10 #include "lib/invocation_mirror.h"
(...skipping 10116 matching lines...) Expand 10 before | Expand all | Expand 10 after
10127 statement = ParseDoWhileStatement(label_name); 10127 statement = ParseDoWhileStatement(label_name);
10128 } else if (token == Token::kSWITCH) { 10128 } else if (token == Token::kSWITCH) {
10129 statement = ParseSwitchStatement(label_name); 10129 statement = ParseSwitchStatement(label_name);
10130 } else if (token == Token::kTRY) { 10130 } else if (token == Token::kTRY) {
10131 statement = ParseTryStatement(label_name); 10131 statement = ParseTryStatement(label_name);
10132 } else if (token == Token::kRETURN) { 10132 } else if (token == Token::kRETURN) {
10133 const TokenPosition return_pos = TokenPos(); 10133 const TokenPosition return_pos = TokenPos();
10134 ConsumeToken(); 10134 ConsumeToken();
10135 if (CurrentToken() != Token::kSEMICOLON) { 10135 if (CurrentToken() != Token::kSEMICOLON) {
10136 const TokenPosition expr_pos = TokenPos(); 10136 const TokenPosition expr_pos = TokenPos();
10137 const int function_level = FunctionLevel();
10137 if (current_function().IsGenerativeConstructor() && 10138 if (current_function().IsGenerativeConstructor() &&
10138 (FunctionLevel() == 0)) { 10139 (function_level == 0)) {
10139 ReportError(expr_pos, 10140 ReportError(expr_pos,
10140 "return of a value is not allowed in constructors"); 10141 "return of a value is not allowed in constructors");
10141 } else if (current_function().IsGeneratorClosure() && 10142 } else if (current_function().IsGeneratorClosure() &&
10142 (FunctionLevel() == 0)) { 10143 (function_level == 0)) {
10143 ReportError(expr_pos, "generator functions may not return a value"); 10144 ReportError(expr_pos, "generator functions may not return a value");
10144 } 10145 }
10145 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); 10146 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
10146 if (I->type_checks() && 10147 if (I->type_checks() &&
10147 current_function().IsAsyncClosure() && (FunctionLevel() == 0)) { 10148 (((function_level == 0) && current_function().IsAsyncClosure()) ||
10149 ((function_level > 0) && current_function().IsAsyncFunction()))) {
10148 // In checked mode, when the declared result type is Future<T>, verify 10150 // In checked mode, when the declared result type is Future<T>, verify
10149 // that the returned expression is of type T or Future<T> as follows: 10151 // that the returned expression is of type T or Future<T> as follows:
10150 // return temp = expr, temp is Future ? temp as Future<T> : temp as T; 10152 // return temp = expr, temp is Future ? temp as Future<T> : temp as T;
10151 // In case of a mismatch, we need a TypeError and not a CastError, so 10153 // In case of a mismatch, we need a TypeError and not a CastError, so
10152 // we do not actually implement an "as" test, but an "assignable" test. 10154 // we do not actually implement an "as" test, but an "assignable" test.
10153 const Function& async_func = 10155 Function& async_func = Function::Handle(Z, current_function().raw());
10154 Function::Handle(Z, current_function().parent_function()); 10156 if (function_level == 0) {
10157 async_func = async_func.parent_function();
10158 }
10155 const AbstractType& result_type = 10159 const AbstractType& result_type =
10156 AbstractType::ZoneHandle(Z, async_func.result_type()); 10160 AbstractType::ZoneHandle(Z, async_func.result_type());
10157 const Class& future_class = 10161 const Class& future_class =
10158 Class::ZoneHandle(Z, I->object_store()->future_class()); 10162 Class::ZoneHandle(Z, I->object_store()->future_class());
10159 ASSERT(!future_class.IsNull()); 10163 ASSERT(!future_class.IsNull());
10160 if (result_type.type_class() == future_class.raw()) { 10164 if (result_type.type_class() == future_class.raw()) {
10161 const TypeArguments& result_type_args = 10165 const TypeArguments& result_type_args =
10162 TypeArguments::ZoneHandle(Z, result_type.arguments()); 10166 TypeArguments::ZoneHandle(Z, result_type.arguments());
10163 if (!result_type_args.IsNull() && (result_type_args.Length() == 1)) { 10167 if (!result_type_args.IsNull() && (result_type_args.Length() == 1)) {
10164 const AbstractType& result_type_arg = 10168 const AbstractType& result_type_arg =
10165 AbstractType::ZoneHandle(Z, result_type_args.TypeAt(0)); 10169 AbstractType::ZoneHandle(Z, result_type_args.TypeAt(0));
10166 LetNode* checked_expr = new(Z) LetNode(expr_pos); 10170 if (function_level == 0) {
10167 LocalVariable* temp = checked_expr->AddInitializer(expr); 10171 // Parsing and generating code for async closure.
10168 temp->set_is_final(); 10172 LetNode* checked_expr = new(Z) LetNode(expr_pos);
10169 const AbstractType& future_type = 10173 LocalVariable* temp = checked_expr->AddInitializer(expr);
10170 AbstractType::ZoneHandle(Z, future_class.RareType()); 10174 temp->set_is_final();
10171 AstNode* is_future = new(Z) LoadLocalNode(expr_pos, temp); 10175 const AbstractType& future_type =
10172 is_future = new(Z) ComparisonNode(expr_pos, 10176 AbstractType::ZoneHandle(Z, future_class.RareType());
10173 Token::kIS, 10177 AstNode* is_future = new(Z) LoadLocalNode(expr_pos, temp);
10174 is_future, 10178 is_future = new(Z) ComparisonNode(expr_pos,
10175 new(Z) TypeNode(expr_pos, 10179 Token::kIS,
10176 future_type)); 10180 is_future,
10177 AstNode* as_future_t = new(Z) LoadLocalNode(expr_pos, temp); 10181 new(Z) TypeNode(expr_pos,
10178 as_future_t = new(Z) AssignableNode(expr_pos, 10182 future_type));
10179 as_future_t, 10183 AstNode* as_future_t = new(Z) LoadLocalNode(expr_pos, temp);
10180 result_type, 10184 as_future_t = new(Z) AssignableNode(expr_pos,
10181 Symbols::FunctionResult()); 10185 as_future_t,
10182 AstNode* as_t = new(Z) LoadLocalNode(expr_pos, temp); 10186 result_type,
10183 as_t = new(Z) AssignableNode(expr_pos, 10187 Symbols::FunctionResult());
10184 as_t, 10188 AstNode* as_t = new(Z) LoadLocalNode(expr_pos, temp);
10185 result_type_arg, 10189 as_t = new(Z) AssignableNode(expr_pos,
10186 Symbols::FunctionResult()); 10190 as_t,
10187 checked_expr->AddNode(new(Z) ConditionalExprNode(expr_pos, 10191 result_type_arg,
10188 is_future, 10192 Symbols::FunctionResult());
10189 as_future_t, 10193 checked_expr->AddNode(new(Z) ConditionalExprNode(expr_pos,
10190 as_t)); 10194 is_future,
10191 expr = checked_expr; 10195 as_future_t,
10196 as_t));
10197 expr = checked_expr;
10198 } else {
10199 // Parsing async function, but not generating async closure code.
10200 if (!result_type_arg.IsInstantiated()) {
10201 // Make sure that the instantiator is captured.
10202 CaptureInstantiator();
10203 }
10204 }
10192 } 10205 }
10193 } 10206 }
10194 } 10207 }
10195 statement = new(Z) ReturnNode(statement_pos, expr); 10208 statement = new(Z) ReturnNode(statement_pos, expr);
10196 } else { 10209 } else {
10197 if (current_function().IsSyncGenClosure() && 10210 if (current_function().IsSyncGenClosure() &&
10198 (FunctionLevel() == 0)) { 10211 (FunctionLevel() == 0)) {
10199 // In a synchronous generator, return without an expression 10212 // In a synchronous generator, return without an expression
10200 // returns false, signaling that the iterator terminates and 10213 // returns false, signaling that the iterator terminates and
10201 // did not yield a value. 10214 // did not yield a value.
(...skipping 4415 matching lines...) Expand 10 before | Expand all | Expand 10 after
14617 const ArgumentListNode& function_args, 14630 const ArgumentListNode& function_args,
14618 const LocalVariable* temp_for_last_arg, 14631 const LocalVariable* temp_for_last_arg,
14619 bool is_super_invocation) { 14632 bool is_super_invocation) {
14620 UNREACHABLE(); 14633 UNREACHABLE();
14621 return NULL; 14634 return NULL;
14622 } 14635 }
14623 14636
14624 } // namespace dart 14637 } // namespace dart
14625 14638
14626 #endif // DART_PRECOMPILED_RUNTIME 14639 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW
« no previous file with comments | « no previous file | tests/language/regress_26668_test.dart » ('j') | tests/language/regress_26668_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698