From 6b9aecbe5fce8bf22f2c8c6351f7b3e4a6960185 Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Wed, 3 Jun 2026 11:32:28 -0700 Subject: [PATCH] [vm,aot] Fix parameter type checks in the implicit setters of covariant-by-class fields Implicit setters of covariant fields (both covariant by declaration and covariant by class aka generic-covariant-impl) need to perform a type check of their argument. It means that inferred type of the field cannot be used as inferred type of parameter of such setter. This change removes such uses of an inferred type of the field, which restores parameter type check which was previously incorrectly optimized out. TEST=runtime/tests/vm/dart/regress_63419_test.dart Fixes https://github.com/dart-lang/sdk/issues/63419 Change-Id: Ie313dbaab51dff15d60ce4390e7e41bdc66ad59d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/509020 Reviewed-by: Slava Egorov Commit-Queue: Alexander Markov --- .../type_flow/unboxing_info.dart | 2 +- runtime/tests/vm/dart/regress_63419_test.dart | 45 +++++++++++++++++++ runtime/vm/compiler/frontend/scope_builder.cc | 3 +- 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 runtime/tests/vm/dart/regress_63419_test.dart diff --git a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart index a528575bbc0..4325bb95c51 100644 --- a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart +++ b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart @@ -194,7 +194,7 @@ class UnboxingInfoManager { // Arguments of implicit setters for covariant fields // cannot be unboxed based on the field type as setter // performs a type check before value is assigned to the field. - if (member.isCovariantByDeclaration) { + if (member.isCovariantByDeclaration || member.isCovariantByClass) { unboxingInfo.argsInfo.length = 0; } else { _applyToArg(member, unboxingInfo, 0, inferredType); diff --git a/runtime/tests/vm/dart/regress_63419_test.dart b/runtime/tests/vm/dart/regress_63419_test.dart new file mode 100644 index 00000000000..f13f2908faf --- /dev/null +++ b/runtime/tests/vm/dart/regress_63419_test.dart @@ -0,0 +1,45 @@ +// Copyright (c) 2026, 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/63419. + +// VMOptions=--compiler-passes=-Inlining + +import 'package:expect/expect.dart'; + +abstract interface class Box1 { + T get x; + void set x(T value); +} + +class StringBox implements Box1 { + @pragma("vm:never-inline") + String x = 'yay'; +} + +abstract interface class Box2 { + T get x; + void set x(T value); +} + +class IntBox implements Box2 { + @pragma("vm:never-inline") + int x = 0; +} + +void main() { + final Box1 box1 = StringBox(); + box1.x = 'xyz'; + Expect.equals('xyz', box1.x); + Expect.throws(() { + box1.x = 123; + }); + + final Box2 box2 = IntBox(); + box2.x = 123; + Expect.equals(123, box2.x); + Expect.throws(() { + box2.x = 'abc'; + }); +} diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc index 862d927c49d..116a4ba8580 100644 --- a/runtime/vm/compiler/frontend/scope_builder.cc +++ b/runtime/vm/compiler/frontend/scope_builder.cc @@ -308,7 +308,8 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() { AbstractType::ZoneHandle(Z, function.ParameterTypeAt(pos)), LocalVariable::kNoKernelOffset, /*is_late=*/false, /*inferred_type_md=*/nullptr, - /*inferred_arg_type_md=*/field.is_covariant() + /*inferred_arg_type_md=*/ + (field.is_covariant() || field.is_generic_covariant_impl()) ? nullptr : &inferred_field_type); } else {