From 59d6206a3db19843d1c7ac8ec29b945c802fd504 Mon Sep 17 00:00:00 2001 From: Nicholas Shahan Date: Tue, 11 Jul 2023 16:35:07 +0000 Subject: [PATCH] [stable][kernel] Fix record type equivalence - Increment index to avoid infinite loop when the first named elements in the two record types are equivalent. - Add some test cases for record types. Fixes: https://github.com/dart-lang/sdk/issues/52817 Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/311929 Change-Id: Iaa4dbf7d2659deeac1eab642cc3aefad9a08f67e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/312709 Commit-Queue: Nicholas Shahan Reviewed-by: Sigmund Cherem Reviewed-by: Kevin Chisholm --- CHANGELOG.md | 3 +++ pkg/kernel/lib/src/dart_type_equivalence.dart | 15 ++++++++------- pkg/kernel/test/dart_type_equivalence_test.dart | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b414a98a942..6b58f2f432b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,13 @@ This is a patch release that: - Fixes a flow in flow analysis that causes it to sometimes ignore destructuring assignments (issue [#52767]). +- Fixes an infinite loop in some web development compiles that include `is` or + `as` expressions involving record types with named fields (issue [#52869]). - Fixes a memory leak in Dart analyzer's file-watching (issue [#52791]). - Fixes a memory leak of file system watcher related data structures (issue [#52793]). [#52767]: https://github.com/dart-lang/sdk/issues/52767 +[#52869]: https://github.com/dart-lang/sdk/issues/52869 [#52791]: https://github.com/dart-lang/sdk/issues/52791 [#52793]: https://github.com/dart-lang/sdk/issues/52793 diff --git a/pkg/kernel/lib/src/dart_type_equivalence.dart b/pkg/kernel/lib/src/dart_type_equivalence.dart index 630108546664..cd7ecbf8c475 100644 --- a/pkg/kernel/lib/src/dart_type_equivalence.dart +++ b/pkg/kernel/lib/src/dart_type_equivalence.dart @@ -129,18 +129,19 @@ class DartTypeEquivalence implements DartTypeVisitor1 { } } - // The named fields of [RecordType]s are supposed to be sorted, so we can - // use a linear search to compare them. - int nodeIndex = 0; - int otherIndex = 0; - while (result && nodeIndex < node.named.length) { - NamedType nodeNamedType = node.named[nodeIndex]; - NamedType otherNamedType = other.named[otherIndex]; + // The named fields of [RecordType]s are supposed to be sorted and we know + // there are the same number of named fields, so we can use a linear + // search to compare them. + int i = 0; + while (result && i < node.named.length) { + NamedType nodeNamedType = node.named[i]; + NamedType otherNamedType = other.named[i]; if (nodeNamedType.name != otherNamedType.name) { result = false; } else { result = nodeNamedType.type.accept1(this, otherNamedType.type); } + i++; } return result; diff --git a/pkg/kernel/test/dart_type_equivalence_test.dart b/pkg/kernel/test/dart_type_equivalence_test.dart index fdb27ebed3cf..8e8f5daf6acc 100644 --- a/pkg/kernel/test/dart_type_equivalence_test.dart +++ b/pkg/kernel/test/dart_type_equivalence_test.dart @@ -162,6 +162,22 @@ void run() { notEqual("Typedef?", "Typedef", equateTopTypes: true); areEqual("Typedef?", "Typedef", equateTopTypes: true, ignoreTopLevelNullability: true); + + // Record types. + areEqual("(int, bool)", "(int, bool)"); + notEqual("(int, bool)", "(int?, bool)"); + notEqual("(int, bool)", "(int, bool?)"); + notEqual("(int, bool)", "({int i, bool b})"); + areEqual("({int i, bool b})", "({int i, bool b})"); + areEqual("({int i, bool b})", "({bool b ,int i})"); + notEqual("({int i, bool b})", "({int? i, bool b})"); + notEqual("({int i, bool b})", "({int i, bool? b})"); + notEqual("({int i, bool b})", "({int n, bool b})"); + notEqual("({int i, bool b})", "({int i, bool t})"); + areEqual("(int, {bool b})", "(int, {bool b})"); + notEqual("(int, {bool b})", "(int?, {bool b})"); + notEqual("(int, {bool b})", "(int, {bool? b})"); + notEqual("(int, {bool b})", "(int, {bool t})"); } void areEqual(String type1, String type2,