diff --git a/pkg/vm/lib/transformations/ffi/finalizable.dart b/pkg/vm/lib/transformations/ffi/finalizable.dart index 84b146967a3c..4fe96f3b6f9b 100644 --- a/pkg/vm/lib/transformations/ffi/finalizable.dart +++ b/pkg/vm/lib/transformations/ffi/finalizable.dart @@ -220,14 +220,15 @@ mixin FinalizableTransformer on Transformer { @override TreeNode visitVariableDeclaration(VariableDeclaration node) { + node = super.visitVariableDeclaration(node) as VariableDeclaration; if (_currentScope == null) { // Global variable. - return super.visitVariableDeclaration(node); + return node; } if (_isFinalizable(node.type)) { _currentScope!.addDeclaration(node); } - return super.visitVariableDeclaration(node); + return node; } @override diff --git a/pkg/vm/testcases/transformations/ffi/regress_49075.dart b/pkg/vm/testcases/transformations/ffi/regress_49075.dart new file mode 100644 index 000000000000..0046fd84be77 --- /dev/null +++ b/pkg/vm/testcases/transformations/ffi/regress_49075.dart @@ -0,0 +1,14 @@ +// Copyright (c) 2022, 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. + +import 'dart:ffi'; + +Future main(List arguments) async { + // ignore: unused_local_variable + final myFinalizable = await MyFinalizable(); +} + +class MyFinalizable implements Finalizable { + MyFinalizable(); +} diff --git a/pkg/vm/testcases/transformations/ffi/regress_49075.dart.expect b/pkg/vm/testcases/transformations/ffi/regress_49075.dart.expect new file mode 100644 index 000000000000..2974867f0ab0 --- /dev/null +++ b/pkg/vm/testcases/transformations/ffi/regress_49075.dart.expect @@ -0,0 +1,45 @@ +library #lib /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "dart:ffi" as ffi; +import "dart:_internal" as _in; +import "dart:async" as asy; + +import "dart:ffi"; + +class MyFinalizable extends core::Object implements ffi::Finalizable { + constructor •() → self::MyFinalizable + : super core::Object::•() { + ; + _in::reachabilityFence(this); + } +} +static method main(core::List arguments) → asy::Future /* futureValueType= void */ /* originally async */ { + final asy::_Future :async_future = new asy::_Future::•(); + core::bool* :is_sync = false; + void :return_value; + (dynamic) → dynamic :async_op_then; + (core::Object, core::StackTrace) → dynamic :async_op_error; + core::int :await_jump_var = 0; + dynamic :await_ctx_var; + dynamic :saved_try_context_var0; + function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding + try { + #L1: + { + [yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFinalizable::•(), :async_op_then, :async_op_error) in null; + final self::MyFinalizable myFinalizable = _in::unsafeCast(:result_or_exception); + _in::reachabilityFence(myFinalizable); + } + asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync); + return; + } + on dynamic catch(dynamic exception, core::StackTrace stack_trace) { + asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync); + } + :async_op_then = asy::_asyncThenWrapperHelper(:async_op); + :async_op_error = asy::_asyncErrorWrapperHelper(:async_op); + :async_op(null, null){() → dynamic}; + :is_sync = true; + return :async_future; +}