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

Unified Diff: runtime/vm/parser.cc

Issue 1847953002: Report wrong async function result type as type error in checked mode (Fixes #26133). (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: address comment Created 4 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/ast.h ('k') | tests/language/async_return_types_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index f0fda88ecb9e24b517f8d808c4d8c08e75b57bbd..4eb855ea435b0f577f500c703b5683edc2b55dff 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(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;
+ }
+ }
+ }
statement = new(Z) ReturnNode(statement_pos, expr);
} else {
if (current_function().IsSyncGenClosure() &&
« no previous file with comments | « runtime/vm/ast.h ('k') | tests/language/async_return_types_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698