Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index 6b4aa4e506659530ba4fd185da49dec49bd357a1..6a89bd0eeffadb3e15b2cae7b8bfbf4ff4aeb173 100644 |
--- a/runtime/vm/parser.cc |
+++ b/runtime/vm/parser.cc |
@@ -10134,24 +10134,28 @@ AstNode* Parser::ParseStatement() { |
ConsumeToken(); |
if (CurrentToken() != Token::kSEMICOLON) { |
const TokenPosition expr_pos = TokenPos(); |
+ const int function_level = FunctionLevel(); |
if (current_function().IsGenerativeConstructor() && |
- (FunctionLevel() == 0)) { |
+ (function_level == 0)) { |
ReportError(expr_pos, |
"return of a value is not allowed in constructors"); |
} else if (current_function().IsGeneratorClosure() && |
- (FunctionLevel() == 0)) { |
+ (function_level == 0)) { |
ReportError(expr_pos, "generator functions may not return a value"); |
} |
AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
if (I->type_checks() && |
- current_function().IsAsyncClosure() && (FunctionLevel() == 0)) { |
+ (((function_level == 0) && current_function().IsAsyncClosure()) || |
+ ((function_level > 0) && current_function().IsAsyncFunction()))) { |
// In checked mode, when the declared result type is Future<T>, verify |
// that the returned expression is of type T or Future<T> as follows: |
// return temp = expr, temp is Future ? temp as Future<T> : temp as T; |
// In case of a mismatch, we need a TypeError and not a CastError, so |
// we do not actually implement an "as" test, but an "assignable" test. |
- const Function& async_func = |
- Function::Handle(Z, current_function().parent_function()); |
+ Function& async_func = Function::Handle(Z, current_function().raw()); |
+ if (function_level == 0) { |
+ async_func = async_func.parent_function(); |
+ } |
const AbstractType& result_type = |
AbstractType::ZoneHandle(Z, async_func.result_type()); |
const Class& future_class = |
@@ -10163,32 +10167,41 @@ AstNode* Parser::ParseStatement() { |
if (!result_type_args.IsNull() && (result_type_args.Length() == 1)) { |
const AbstractType& result_type_arg = |
AbstractType::ZoneHandle(Z, result_type_args.TypeAt(0)); |
- LetNode* checked_expr = new(Z) LetNode(expr_pos); |
- LocalVariable* temp = checked_expr->AddInitializer(expr); |
- temp->set_is_final(); |
- const AbstractType& future_type = |
- AbstractType::ZoneHandle(Z, future_class.RareType()); |
- AstNode* is_future = new(Z) LoadLocalNode(expr_pos, temp); |
- is_future = new(Z) ComparisonNode(expr_pos, |
- Token::kIS, |
- is_future, |
- new(Z) TypeNode(expr_pos, |
- future_type)); |
- AstNode* as_future_t = new(Z) LoadLocalNode(expr_pos, temp); |
- as_future_t = new(Z) AssignableNode(expr_pos, |
- as_future_t, |
- result_type, |
- Symbols::FunctionResult()); |
- AstNode* as_t = new(Z) LoadLocalNode(expr_pos, temp); |
- as_t = new(Z) AssignableNode(expr_pos, |
- as_t, |
- result_type_arg, |
- Symbols::FunctionResult()); |
- checked_expr->AddNode(new(Z) ConditionalExprNode(expr_pos, |
- is_future, |
- as_future_t, |
- as_t)); |
- expr = checked_expr; |
+ if (function_level == 0) { |
+ // Parsing and generating code for async closure. |
+ LetNode* checked_expr = new(Z) LetNode(expr_pos); |
+ LocalVariable* temp = checked_expr->AddInitializer(expr); |
+ temp->set_is_final(); |
+ const AbstractType& future_type = |
+ AbstractType::ZoneHandle(Z, future_class.RareType()); |
+ AstNode* is_future = new(Z) LoadLocalNode(expr_pos, temp); |
+ is_future = new(Z) ComparisonNode(expr_pos, |
+ Token::kIS, |
+ is_future, |
+ new(Z) TypeNode(expr_pos, |
+ future_type)); |
+ AstNode* as_future_t = new(Z) LoadLocalNode(expr_pos, temp); |
+ as_future_t = new(Z) AssignableNode(expr_pos, |
+ as_future_t, |
+ result_type, |
+ Symbols::FunctionResult()); |
+ AstNode* as_t = new(Z) LoadLocalNode(expr_pos, temp); |
+ as_t = new(Z) AssignableNode(expr_pos, |
+ as_t, |
+ result_type_arg, |
+ Symbols::FunctionResult()); |
+ checked_expr->AddNode(new(Z) ConditionalExprNode(expr_pos, |
+ is_future, |
+ as_future_t, |
+ as_t)); |
+ expr = checked_expr; |
+ } else { |
+ // Parsing async function, but not generating async closure code. |
+ if (!result_type_arg.IsInstantiated()) { |
+ // Make sure that the instantiator is captured. |
+ CaptureInstantiator(); |
+ } |
+ } |
} |
} |
} |