From d82e84ca2fa70bde2c1e01c1cec1e009fc0e1a7e Mon Sep 17 00:00:00 2001 From: Nate Biggs Date: Mon, 6 Jan 2025 10:23:43 -0800 Subject: [PATCH] [dart2wasm] Fix tearoff codegen on boxed types. The struct type for closures requires the context value be a struct. If the tearoff is on an unboxed value, it first has to be boxed before being used to create the closure struct. The new test currently fails at runtime (or via assertions at compile time) with this error: "BoxedInt.abs tear-off" failed: struct.new[2] expected type (ref struct), found local.get of type i64 Change-Id: Ie861bc12a34b21f8b3415edadf55ce3d59f97580 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/402560 Reviewed-by: Martin Kustermann Commit-Queue: Nate Biggs --- pkg/dart2wasm/lib/code_generator.dart | 3 +++ tests/web/wasm/boxed_value_tearoff_test.dart | 10 ++++++++++ 2 files changed, 13 insertions(+) create mode 100644 tests/web/wasm/boxed_value_tearoff_test.dart diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart index 38e5219354c..5c3886ed6c4 100644 --- a/pkg/dart2wasm/lib/code_generator.dart +++ b/pkg/dart2wasm/lib/code_generator.dart @@ -3256,6 +3256,9 @@ class TearOffCodeGenerator extends AstCodeGenerator { b.pushObjectHeaderFields(info); b.local_get(paramLocals[0]); // `this` as context + // The closure requires a struct value so box `this` if necessary. + translator.convertType(b, paramLocals[0].type, + struct.fields[FieldIndex.closureContext].type.unpacked); translator.globals.readGlobal(b, closure.vtable); types.makeType(this, functionType); b.struct_new(struct); diff --git a/tests/web/wasm/boxed_value_tearoff_test.dart b/tests/web/wasm/boxed_value_tearoff_test.dart new file mode 100644 index 00000000000..f1be75ba0bc --- /dev/null +++ b/tests/web/wasm/boxed_value_tearoff_test.dart @@ -0,0 +1,10 @@ +// Copyright (c) 2024, 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 'package:expect/expect.dart'; + +void main() { + final tearoff = (-4).abs; + Expect.equals(tearoff(), 4); +}