From f4b4e5e297dfa9ecd2ff5b4b380fa89a5c8441da Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Tue, 11 Mar 2025 03:57:09 -0700 Subject: [PATCH] [dart2wasm] Fix incorrect setup of checked entrypoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A method may be overriden multiple times, the overriden methods may add optional parameters. Dart2wasm generates a signature for such selectors that includes all optional parameters from all overriden methods. That means * callers may pass more arguments than the signature of the target => it passes dummy values * implementations get more parameters passed than their Dart function => it ignores them The checked/unchecked entry functions need to also support this mechanism. Issue https://github.com/dart-lang/sdk/issues/60148 Change-Id: Ifb60c44d3c5e5b6e374a15731723e16d22bfc094 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/414720 Reviewed-by: Ömer Ağacan Commit-Queue: Martin Kustermann --- pkg/dart2wasm/lib/code_generator.dart | 12 +++++++-- tests/language/regress/regress60148_test.dart | 27 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 tests/language/regress/regress60148_test.dart diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart index 5a7176dfb6e..3c5087d1470 100644 --- a/pkg/dart2wasm/lib/code_generator.dart +++ b/pkg/dart2wasm/lib/code_generator.dart @@ -379,10 +379,18 @@ abstract class AstCodeGenerator canSafelyOmitImplicitChecks: !translator.needToCheckTypesFor(member)); } + void setupParametersForCheckedEntry(Member member) { + assert(member.isInstanceMember); + assert(translator.needToCheckTypesFor(member)); + setupParameters(member.checkedEntryReference, + canSafelyOmitImplicitChecks: false); + } + void setupParametersForUncheckedEntry(Member member) { assert(member.isInstanceMember); assert(translator.needToCheckTypesFor(member)); - setupParameters(member.reference, canSafelyOmitImplicitChecks: true); + setupParameters(member.uncheckedEntryReference, + canSafelyOmitImplicitChecks: true); } void setupContexts(Member member) { @@ -3299,7 +3307,7 @@ class SynchronousProcedureCodeGenerator extends AstCodeGenerator { final function = member.function; final signature = translator.signatureForDirectCall(member.bodyReference); if (checked) { - setupParametersForNormalEntry(member); + setupParametersForCheckedEntry(member); } else { setupParametersForUncheckedEntry(member); } diff --git a/tests/language/regress/regress60148_test.dart b/tests/language/regress/regress60148_test.dart new file mode 100644 index 00000000000..24ea8efd8b6 --- /dev/null +++ b/tests/language/regress/regress60148_test.dart @@ -0,0 +1,27 @@ +// Copyright (c) 2025, 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:async'; + +import 'package:expect/expect.dart'; + +main() async { + final l = >[B(), C()]; + Expect.equals('B.foo(1, first=1)', l[0].foo(1)); + Expect.equals('C.foo(2, second=true)', l[1].foo(2)); + Expect.equals('B.foo(3, first=2)', B().foo(3, first: 2)); + Expect.equals('C.foo(4, second=false)', C().foo(4, second: false)); +} + +abstract class A { + String foo(T a); +} + +class B extends A { + String foo(T a, {int first = 1}) => 'B.foo($a, first=$first)'; +} + +class C extends A { + String foo(T a, {bool second = true}) => 'C.foo($a, second=$second)'; +}