[cfe] Check primitive equals in legacy libraries
This enables the check for primitive equals in switch cases in
legacy libraries.
Change-Id: Iddc464f39525d5167a5c6e8c40c95acc3c245d76
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/231701
Reviewed-by: Joshua Litt <joshualitt@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 9aca3e3..4bb0a08 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -728,7 +728,7 @@
TreeNode result = super.visitSwitchStatement(node, removalSentinel);
Library library = constantEvaluator.libraryOf(node);
// ignore: unnecessary_null_comparison
- if (library != null && library.isNonNullableByDefault) {
+ if (library != null) {
for (SwitchCase switchCase in node.cases) {
for (Expression caseExpression in switchCase.expressions) {
if (caseExpression is ConstantExpression) {
diff --git a/tests/language/type/constants_test.dart b/tests/language/type/constants_test.dart
index 560e485..2a35320 100644
--- a/tests/language/type/constants_test.dart
+++ b/tests/language/type/constants_test.dart
@@ -15,6 +15,9 @@
const Type numType = num;
+const bool fromEnvironment =
+ const bool.fromEnvironment("foo", defaultValue: true);
+
Type argumentType<T>() => T;
void testSwitch<T extends MyType>(args) {
@@ -22,7 +25,7 @@
for (int i = 0; i < types.length; i++) {
switch (types[i]) {
// Must be type literal or not override `==`.
- case const MyType(): //# 01: compile-time error
+ case const MyType(0): //# 01: compile-time error
// Must not be type variable.
case T: //# 02: compile-time error
@@ -39,6 +42,8 @@
throw "unreachable: num #$i";
case MyType:
break;
+ // Must be type literal or not override `==`.
+ case fromEnvironment ? const MyType(1) : Type: //# 07: compile-time error
default:
throw "unreachable: default #$i";
}
@@ -48,7 +53,7 @@
void testMaps<T extends MyType>(args) {
const map = {
// Must be type literal or not override `==`.
- MyType(): 0, //# 04: compile-time error
+ MyType(0): 0, //# 04: compile-time error
// Must not be type variable.
T: 0, //# 05: compile-time error
@@ -61,6 +66,8 @@
int: 1,
String: 2,
numType: 3,
+ // Must be type literal or not override `==`.
+ fromEnvironment ? const MyType(1) : Type: 4, //# 08: compile-time error
};
if (map[MyType] != 0) throw "Map Error: ${MyType} as literal";
if (map[T] != 0) throw "Map Error: ${T} as type argument";
@@ -76,7 +83,8 @@
// An implementation of `Type` which overrides `==`,
// but is not the value of a constant type literal.
class MyType implements Type {
- const MyType();
+ final int value;
+ const MyType(this.value);
int get hashCode => 0;
bool operator ==(Object other) => identical(this, other);
}
diff --git a/tests/language_2/const/switch2_test.dart b/tests/language_2/const/switch2_test.dart
index 772846e..ce881a4 100644
--- a/tests/language_2/const/switch2_test.dart
+++ b/tests/language_2/const/switch2_test.dart
@@ -13,6 +13,7 @@
// [analyzer] COMPILE_TIME_ERROR.SWITCH_EXPRESSION_NOT_ASSIGNABLE
case 0.0:
// ^
+ // [cfe] Case expression '0.0' does not have a primitive operator '=='.
// [cfe] Type 'int' of the switch expression isn't assignable to the type 'double' of this case expression.
print("illegal");
break;
diff --git a/tests/language_2/switch/bad_case_test.dart b/tests/language_2/switch/bad_case_test.dart
index 3e3a340..85c88fa 100644
--- a/tests/language_2/switch/bad_case_test.dart
+++ b/tests/language_2/switch/bad_case_test.dart
@@ -34,8 +34,12 @@
//^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
case 3.14:
+ // ^
+ // [cfe] Case expression '3.14' does not have a primitive operator '=='.
return "Pi";
case 2.71828:
+ // ^
+ // [cfe] Case expression '2.71828' does not have a primitive operator '=='.
return "Huh?";
}
return null;
diff --git a/tests/language_2/switch/case_test.dart b/tests/language_2/switch/case_test.dart
index af15ac6..fa519fd0 100644
--- a/tests/language_2/switch/case_test.dart
+++ b/tests/language_2/switch/case_test.dart
@@ -35,6 +35,8 @@
//^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
case const A.B(): Expect.fail("bad switch"); break;
+ // ^
+ // [cfe] Case expression 'B {}' does not have a primitive operator '=='.
}
switch (new C()) {
@@ -59,5 +61,7 @@
case const A.B(): Expect.fail("bad switch"); break;
// ^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_CASE_EXPRESSION_TYPES
+ // ^
+ // [cfe] Case expression 'B {}' does not have a primitive operator '=='.
}
}
diff --git a/tests/language_2/type/constants_test.dart b/tests/language_2/type/constants_test.dart
index ded5300..cda34ff 100644
--- a/tests/language_2/type/constants_test.dart
+++ b/tests/language_2/type/constants_test.dart
@@ -17,6 +17,9 @@
const Type numType = num;
+const bool fromEnvironment =
+ const bool.fromEnvironment("foo", defaultValue: true);
+
Type argumentType<T>() => T;
void testSwitch<T extends MyType>(args) {
@@ -24,7 +27,7 @@
for (int i = 0; i < types.length; i++) {
switch (types[i]) {
// Must be type literal or not override `==`.
- case const MyType(): //# 01: compile-time error
+ case const MyType(0): //# 01: compile-time error
// Must not be type variable.
case T: //# 02: compile-time error
@@ -41,6 +44,8 @@
throw "unreachable: num #$i";
case MyType:
break;
+ // Must be type literal or not override `==`.
+ case fromEnvironment ? const MyType(1) : Type: //# 07: compile-time error
default:
throw "unreachable: default #$i";
}
@@ -50,7 +55,7 @@
void testMaps<T extends MyType>(args) {
const map = {
// Must be type literal or not override `==`.
- MyType(): 0, //# 04: compile-time error
+ MyType(0): 0, //# 04: compile-time error
// Must not be type variable.
T: 0, //# 05: compile-time error
@@ -63,6 +68,8 @@
int: 1,
String: 2,
numType: 3,
+ // Must be type literal or not override `==`.
+ fromEnvironment ? const MyType(1) : Type: 4, //# 08: compile-time error
};
if (map[MyType] != 0) throw "Map Error: ${MyType} as literal";
if (map[T] != 0) throw "Map Error: ${T} as type argument";
@@ -78,7 +85,8 @@
// An implementation of `Type` which overrides `==`,
// but is not the value of a constant type literal.
class MyType implements Type {
- const MyType();
+ final int value;
+ const MyType(this.value);
int get hashCode => 0;
bool operator ==(Object other) => identical(this, other);
}