Chromium Code Reviews| Index: runtime/vm/parser.cc |
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
| index f0fda88ecb9e24b517f8d808c4d8c08e75b57bbd..7327ef4a99d3d330e8b8aeb602301780ed0ad732 100644 |
| --- a/runtime/vm/parser.cc |
| +++ b/runtime/vm/parser.cc |
| @@ -10028,6 +10028,56 @@ AstNode* Parser::ParseStatement() { |
| ReportError(expr_pos, "generator functions may not return a value"); |
| } |
| AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| + if (I->type_checks() && |
| + current_function().IsAsyncClosure() && |
| + (current_block_->scope->function_level() == 0)) { |
| + // 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()); |
| + const AbstractType& result_type = |
| + AbstractType::ZoneHandle(Z, async_func.result_type()); |
| + const Class& future_class = |
| + Class::ZoneHandle(Z, I->object_store()->future_class()); |
| + ASSERT(!future_class.IsNull()); |
| + if (result_type.type_class() == future_class.raw()) { |
| + const TypeArguments& result_type_args = |
| + TypeArguments::ZoneHandle(Z, result_type.arguments()); |
| + 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(statement_pos); |
|
hausner
2016/05/09 21:42:34
Should this point to the expression being returned
regis
2016/05/09 21:58:22
Good point! I replaced all occurrences of statemen
|
| + 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(statement_pos, temp); |
| + is_future = new(Z) ComparisonNode(statement_pos, |
| + Token::kIS, |
| + is_future, |
| + new(Z) TypeNode(statement_pos, |
| + future_type)); |
| + AstNode* as_future_t = new(Z) LoadLocalNode(statement_pos, temp); |
| + as_future_t = new(Z) AssignableNode(statement_pos, |
| + as_future_t, |
| + result_type, |
| + Symbols::FunctionResult()); |
| + AstNode* as_t = new(Z) LoadLocalNode(statement_pos, temp); |
| + as_t = new(Z) AssignableNode(statement_pos, |
| + as_t, |
| + result_type_arg, |
| + Symbols::FunctionResult()); |
| + checked_expr->AddNode(new(Z) ConditionalExprNode(statement_pos, |
| + is_future, |
| + as_future_t, |
| + as_t)); |
| + expr = checked_expr; |
| + } |
| + } |
| + } |
| statement = new(Z) ReturnNode(statement_pos, expr); |
| } else { |
| if (current_function().IsSyncGenClosure() && |