diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index 798174df4d7f..6bf2d87a0baa 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -4869,17 +4869,28 @@ Fragment StreamingFlowGraphBuilder::BuildReturnStatement() { if (instructions.is_open()) { if (inside_try_finally) { - ASSERT(scopes()->finally_return_variable != NULL); + LocalVariable* const finally_return_variable = + scopes()->finally_return_variable; + ASSERT(finally_return_variable != nullptr); const Function& function = parsed_function()->function(); if (NeedsDebugStepCheck(function, position)) { instructions += DebugStepCheck(position); } - instructions += StoreLocal(position, scopes()->finally_return_variable); + instructions += StoreLocal(position, finally_return_variable); instructions += Drop(); - instructions += TranslateFinallyFinalizers(NULL, -1); + const intptr_t target_context_depth = + finally_return_variable->is_captured() + ? finally_return_variable->owner()->context_level() + : -1; + instructions += TranslateFinallyFinalizers(nullptr, target_context_depth); if (instructions.is_open()) { - instructions += LoadLocal(scopes()->finally_return_variable); + const intptr_t saved_context_depth = B->context_depth_; + if (finally_return_variable->is_captured()) { + B->context_depth_ = target_context_depth; + } + instructions += LoadLocal(finally_return_variable); instructions += Return(TokenPosition::kNoSource); + B->context_depth_ = saved_context_depth; } } else { instructions += Return(position); diff --git a/tests/language/async_star/regression_47610_test.dart b/tests/language/async_star/regression_47610_test.dart new file mode 100644 index 000000000000..9bb4ce235871 --- /dev/null +++ b/tests/language/async_star/regression_47610_test.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Regression test for https://github.com/dart-lang/sdk/issues/47610. +// Tests returning value from a deep context depth along with +// breaking from 'await for'. + +import "dart:async"; +import "package:expect/expect.dart"; +import "package:async_helper/async_helper.dart"; + +Stream foo() async* { + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + for (int k = 0; k < 2; ++k) { + yield i + j + k; + } + } + } +} + +void test() async { + await for (var x in foo()) { + Expect.equals(0, x); + break; + } +} + +void main() { + asyncTest(test); +} diff --git a/tests/language_2/async_star/regression_47610_test.dart b/tests/language_2/async_star/regression_47610_test.dart new file mode 100644 index 000000000000..4fd78150f904 --- /dev/null +++ b/tests/language_2/async_star/regression_47610_test.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// @dart = 2.9 + +// Regression test for https://github.com/dart-lang/sdk/issues/47610. +// Tests returning value from a deep context depth along with +// breaking from 'await for'. + +import "dart:async"; +import "package:expect/expect.dart"; +import "package:async_helper/async_helper.dart"; + +Stream foo() async* { + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + for (int k = 0; k < 2; ++k) { + yield i + j + k; + } + } + } +} + +void test() async { + await for (var x in foo()) { + Expect.equals(0, x); + break; + } +} + +void main() { + asyncTest(test); +}