From 2b396dd95a60d7b62b8673ee2be3649b108808d0 Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Thu, 1 Feb 2024 11:38:58 +0000 Subject: [PATCH] [dart2wasm] Fix type substitution bug if records are involved Fixes https://github.com/dart-lang/sdk/issues/54794 Change-Id: I13b4ae619fad7d7e00f4a17e199b85ebea4e6de7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/349680 Commit-Queue: Martin Kustermann Reviewed-by: Slava Egorov --- sdk/lib/_internal/wasm/lib/type.dart | 10 ++++++++++ tests/web/wasm/regress_54794_test.dart | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/web/wasm/regress_54794_test.dart diff --git a/sdk/lib/_internal/wasm/lib/type.dart b/sdk/lib/_internal/wasm/lib/type.dart index c1de560c813..26c29c94a22 100644 --- a/sdk/lib/_internal/wasm/lib/type.dart +++ b/sdk/lib/_internal/wasm/lib/type.dart @@ -736,6 +736,16 @@ class _TypeUniverse { assert(rootFunction == null); return substituteInterfaceTypeParameter( type.as<_InterfaceTypeParameterType>(), substitutions); + } else if (type.isRecord) { + final recordType = type.as<_RecordType>(); + final fieldTypes = WasmArray<_Type>.filled( + recordType.fieldTypes.length, _literal()); + for (int i = 0; i < recordType.fieldTypes.length; i++) { + fieldTypes[i] = substituteTypeArgument( + recordType.fieldTypes[i], substitutions, rootFunction); + } + return _RecordType( + recordType.names, fieldTypes, recordType.isDeclaredNullable); } else if (type.isFunction) { _FunctionType functionType = type.as<_FunctionType>(); bool isRoot = identical(type, rootFunction); diff --git a/tests/web/wasm/regress_54794_test.dart b/tests/web/wasm/regress_54794_test.dart new file mode 100644 index 00000000000..4737dacb501 --- /dev/null +++ b/tests/web/wasm/regress_54794_test.dart @@ -0,0 +1,25 @@ +// 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'; + +main() { + final dynamic object = int.parse('1') == 1 ? Sub() : 1; + + Expect.isTrue(isBase(object)); + Expect.isTrue(isBase(object)); + Expect.isTrue(isBase<(dynamic, dynamic)>(object)); + Expect.isTrue(isBase<(int, dynamic)>(object)); + Expect.isTrue(isBase<(dynamic, String)>(object)); + Expect.isTrue(isBase<(int, String)>(object)); + + Expect.isFalse(isBase<(String, dynamic)>(object)); + Expect.isFalse(isBase<(dynamic, int)>(object)); +} + +bool isBase(dynamic o) => o is Base; + +class Base {} + +class Sub implements Base<(A, B)> {}