[cfe] Remove a side effect from computeConstCanonicalType
Closes #44857.
Bug: https://github.com/dart-lang/sdk/issues/44857
Change-Id: I1082fded9a0b06cbcf30c484975b0cf464db75a4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182781
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/testcases/nnbd/issue44857.dart b/pkg/front_end/testcases/nnbd/issue44857.dart
new file mode 100644
index 0000000..96ac4d5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44857.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2021, 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.
+
+typedef F = Never Function(void Function<T extends Never>(T));
+
+void main() {
+ const c = F;
+ print("Are $c, $F identical?");
+ print(identical(c, F));
+}
diff --git a/pkg/front_end/testcases/nnbd/issue44857.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue44857.dart.outline.expect
new file mode 100644
index 0000000..82e5613
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44857.dart.outline.expect
@@ -0,0 +1,6 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+typedef F = (<T extends Never = dynamic>(T) → void) → Never;
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/nnbd/issue44857.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue44857.dart.strong.expect
new file mode 100644
index 0000000..4a6c15d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44857.dart.strong.expect
@@ -0,0 +1,13 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = (<T extends Never = dynamic>(T) → void) → Never;
+static method main() → void {
+ core::print("Are ${#C1}, ${#C1} identical?");
+ core::print(core::identical(#C1, #C1));
+}
+
+constants {
+ #C1 = TypeLiteralConstant((<T extends Never = dynamic>(Never) → void) → Never)
+}
diff --git a/pkg/front_end/testcases/nnbd/issue44857.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue44857.dart.strong.transformed.expect
new file mode 100644
index 0000000..3ddde37
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44857.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = (<T extends Never = dynamic>(T) → void) → Never;
+static method main() → void {
+ core::print("Are ${#C1}, ${#C1} identical?");
+ core::print(core::identical(#C1, #C1));
+}
+
+constants {
+ #C1 = TypeLiteralConstant((<T extends Never = dynamic>(Never) → void) → Never)
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///issue44857.dart:10:9 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 4, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd/issue44857.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue44857.dart.textual_outline.expect
new file mode 100644
index 0000000..cb283ab
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44857.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+typedef F = Never Function(void Function<T extends Never>(T));
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue44857.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue44857.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cb283ab
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44857.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+typedef F = Never Function(void Function<T extends Never>(T));
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue44857.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue44857.dart.weak.expect
new file mode 100644
index 0000000..ad063b4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44857.dart.weak.expect
@@ -0,0 +1,13 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = (<T extends Never = dynamic>(T) → void) → Never;
+static method main() → void {
+ core::print("Are ${#C1}, ${#C1} identical?");
+ core::print(core::identical(#C1, #C1));
+}
+
+constants {
+ #C1 = TypeLiteralConstant((<T extends Never* = Never*>(Never*) →* void) →* Never*)
+}
diff --git a/pkg/front_end/testcases/nnbd/issue44857.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue44857.dart.weak.transformed.expect
new file mode 100644
index 0000000..dd62920
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44857.dart.weak.transformed.expect
@@ -0,0 +1,17 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = (<T extends Never = dynamic>(T) → void) → Never;
+static method main() → void {
+ core::print("Are ${#C1}, ${#C1} identical?");
+ core::print(core::identical(#C1, #C1));
+}
+
+constants {
+ #C1 = TypeLiteralConstant((<T extends Never* = Never*>(Never*) →* void) →* Never*)
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///issue44857.dart:10:9 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 4, effectively constant: 1
diff --git a/pkg/kernel/lib/src/const_canonical_type.dart b/pkg/kernel/lib/src/const_canonical_type.dart
index 9a1dd42..186c980 100644
--- a/pkg/kernel/lib/src/const_canonical_type.dart
+++ b/pkg/kernel/lib/src/const_canonical_type.dart
@@ -112,14 +112,15 @@
assert(type.declaredNullability == Nullability.nonNullable);
List<TypeParameter> canonicalizedTypeParameters;
- Map<TypeParameter, DartType> substitutionMap;
+ Substitution substitution;
if (type.typeParameters.isEmpty) {
canonicalizedTypeParameters = const <TypeParameter>[];
- substitutionMap = const <TypeParameter, DartType>{};
+ substitution = null;
} else {
- substitutionMap = <TypeParameter, DartType>{};
- canonicalizedTypeParameters =
- new List<TypeParameter>.of(type.typeParameters, growable: false);
+ FreshTypeParameters freshTypeParameters =
+ getFreshTypeParameters(type.typeParameters);
+ substitution = freshTypeParameters.substitution;
+ canonicalizedTypeParameters = freshTypeParameters.freshTypeParameters;
for (TypeParameter parameter in canonicalizedTypeParameters) {
parameter.bound = computeConstCanonicalType(parameter.bound, coreTypes,
isNonNullableByDefault: isNonNullableByDefault);
@@ -130,11 +131,6 @@
for (int i = 0; i < canonicalizedTypeParameters.length; ++i) {
canonicalizedTypeParameters[i].defaultType = defaultTypes[i];
}
- for (int i = 0; i < canonicalizedTypeParameters.length; ++i) {
- substitutionMap[canonicalizedTypeParameters[i]] =
- new TypeParameterType.forAlphaRenaming(
- type.typeParameters[i], canonicalizedTypeParameters[i]);
- }
}
List<DartType> canonicalizedPositionalParameters;
@@ -147,8 +143,8 @@
DartType canonicalized = computeConstCanonicalType(
canonicalizedPositionalParameters[i], coreTypes,
isNonNullableByDefault: isNonNullableByDefault);
- if (substitutionMap.isNotEmpty) {
- canonicalized = substitute(canonicalized, substitutionMap);
+ if (substitution != null) {
+ canonicalized = substitution.substituteType(canonicalized);
}
canonicalizedPositionalParameters[i] = canonicalized;
}
@@ -164,8 +160,8 @@
DartType canonicalized = computeConstCanonicalType(
canonicalizedNamedParameters[i].type, coreTypes,
isNonNullableByDefault: isNonNullableByDefault);
- if (substitutionMap.isNotEmpty) {
- canonicalized = substitute(canonicalized, substitutionMap);
+ if (substitution != null) {
+ canonicalized = substitution.substituteType(canonicalized);
}
canonicalizedNamedParameters[i] = new NamedType(
canonicalizedNamedParameters[i].name, canonicalized,
@@ -176,9 +172,9 @@
DartType canonicalizedReturnType = computeConstCanonicalType(
type.returnType, coreTypes,
isNonNullableByDefault: isNonNullableByDefault);
- if (substitutionMap.isNotEmpty) {
+ if (substitution != null) {
canonicalizedReturnType =
- substitute(canonicalizedReturnType, substitutionMap);
+ substitution.substituteType(canonicalizedReturnType);
}
// Canonicalize typedef type, just in case.