[cfe/ffi] Test `Finalizable`s in extension methods
`Finalizable`s with extension methods work by virtue of being
desugared into static methods and the `Finalizable`s being normal
arguments.
If we ever change the representation of extension methods,
`Finalizable`s would need to be treated specially. This test will
catch that.
TEST=pkg/vm/test/transformations/ffi_test.dart
Bug: https://github.com/dart-lang/sdk/issues/49643#issuecomment-1214847853
Change-Id: I68cfbc098386a88495d37417c6eb7295b89bfb95
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255123
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_extension_method.dart b/pkg/vm/testcases/transformations/ffi/finalizable_extension_method.dart
new file mode 100644
index 0000000..65e2d81
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_extension_method.dart
@@ -0,0 +1,31 @@
+// 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.
+
+// @dart=2.16
+
+import 'dart:ffi';
+
+class Foo implements Finalizable {}
+
+void main() {
+ final foo = Foo();
+ foo.bar();
+ Object().baz(foo);
+}
+
+extension on Finalizable {
+ int bar() {
+ print('123');
+ // Should generate a fence for `this` before returning 4.
+ return 4;
+ }
+}
+
+extension on Object {
+ int baz(Foo foo) {
+ print('456');
+ // Should generate a fence for `foo` before returning 5.
+ return 5;
+ }
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_extension_method.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_extension_method.dart.expect
new file mode 100644
index 0000000..24ca399
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_extension_method.dart.expect
@@ -0,0 +1,59 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class Foo extends core::Object implements ffi::Finalizable {
+ synthetic constructor •() → self::Foo
+ : super core::Object::•()
+ ;
+}
+extension _extension#0 on ffi::Finalizable {
+ method bar = self::_extension#0|bar;
+ tearoff bar = self::_extension#0|get#bar;
+}
+extension _extension#1 on core::Object {
+ method baz = self::_extension#1|baz;
+ tearoff baz = self::_extension#1|get#baz;
+}
+static method main() → void {
+ final self::Foo foo = new self::Foo::•();
+ self::_extension#0|bar(foo);
+ self::_extension#1|baz(new core::Object::•(), foo);
+ _in::reachabilityFence(foo);
+}
+static method _extension#0|bar(lowered final ffi::Finalizable #this) → core::int {
+ core::print("123");
+ return block {
+ final core::int :expressionValueWrappedFinalizable = 4;
+ _in::reachabilityFence(#this);
+ } =>:expressionValueWrappedFinalizable;
+}
+static method _extension#0|get#bar(lowered final ffi::Finalizable #this) → () → core::int {
+ return block {
+ final () → core::int :expressionValueWrappedFinalizable = () → core::int {
+ return block {
+ final core::int :expressionValueWrappedFinalizable = self::_extension#0|bar(#this);
+ _in::reachabilityFence(#this);
+ } =>:expressionValueWrappedFinalizable;
+ };
+ _in::reachabilityFence(#this);
+ } =>:expressionValueWrappedFinalizable;
+}
+static method _extension#1|baz(lowered final core::Object #this, self::Foo foo) → core::int {
+ core::print("456");
+ return block {
+ final core::int :expressionValueWrappedFinalizable = 5;
+ _in::reachabilityFence(foo);
+ } =>:expressionValueWrappedFinalizable;
+}
+static method _extension#1|get#baz(lowered final core::Object #this) → (self::Foo) → core::int
+ return (self::Foo foo) → core::int {
+ return block {
+ final core::int :expressionValueWrappedFinalizable = self::_extension#1|baz(#this, foo);
+ _in::reachabilityFence(foo);
+ } =>:expressionValueWrappedFinalizable;
+ };