[cfe] Promote matched expression in relational pattern

Closes #52123

Change-Id: I702524479d1abe83eb67e801454f03a88febe434
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/298600
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart b/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart
index dbe5fda..39644ff 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart
@@ -566,6 +566,8 @@
   @override
   DelayedExpression visitRelationalPattern(
       RelationalPattern node, CacheableExpression matchedExpression) {
+    matchedExpression = matchedExpression.promote(node.matchedValueType!);
+
     CacheableExpression constant = matchingCache.createConstantExpression(
         node.expressionValue!, node.expressionType!,
         fileOffset: node.expression.fileOffset);
@@ -675,8 +677,7 @@
   @override
   DelayedExpression visitVariablePattern(
       VariablePattern node, CacheableExpression matchedExpression) {
-    DartType matchedType = node.matchedValueType!;
-    matchedExpression = matchedExpression.promote(matchedType);
+    matchedExpression = matchedExpression.promote(node.matchedValueType!);
     DelayedExpression? matchingExpression;
     if (node.type != null) {
       matchingExpression = new DelayedIsExpression(
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.expect
index 5a33af6..ac6ec72 100644
--- a/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.expect
+++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.expect
@@ -39,14 +39,14 @@
     hoisted core::int a1;
     final synthesized dynamic #0#0 = x1;
     final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
-    if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) {
+    if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) {
       return a1;
     }
     else {
       hoisted core::int a1;
       final synthesized dynamic #1#0 = x1;
       final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
-      if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+      if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
         return a1;
       }
       else {
@@ -86,7 +86,7 @@
     {
       lowered hoisted core::int a3#case#0;
       lowered hoisted core::String a3#case#1;
-      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") {
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") {
         {
           return 1;
         }
@@ -110,7 +110,7 @@
     {
       lowered hoisted core::int a4#case#0;
       lowered hoisted core::String a4#case#1;
-      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) {
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) {
         {
           return 1;
         }
@@ -134,7 +134,7 @@
     {
       {
         hoisted core::int a5;
-        if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+        if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
           #t11 = 1;
           break #L4;
         }
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.transformed.expect
index fd24527..2858ff3 100644
--- a/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.transformed.expect
@@ -2,18 +2,199 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/patterns/issue51971_2.dart:66:23: Error: Not a constant expression.
-//   list8.addAll(const [x8]);
-//                       ^^
+// pkg/front_end/testcases/patterns/issue51971_2.dart:6:27: Error: Read of a non-const variable is not a constant expression.
+//   if (x1 case int a1 && < a1 || int a1) { // Error.
+//                           ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:8:44: Error: Read of a non-const variable is not a constant expression.
+//   } else if (x1 case int a1 || int a1 && < a1) { // Error.
+//                                            ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:27:22: Error: Read of a non-const variable is not a constant expression.
+//     case int a3 && < a3: // Error.
+//                      ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:28:26: Error: Read of a non-const variable is not a constant expression.
+//     case String a3 && == a3: // Error.
+//                          ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:37:22: Error: Read of a non-const variable is not a constant expression.
+//     case int a4 && < a4 when a4 > 0: // Error.
+//                      ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:38:26: Error: Read of a non-const variable is not a constant expression.
+//     case String a4 && == a4 when a4.startsWith("f"): // Error.
+//                          ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:47:17: Error: Read of a non-const variable is not a constant expression.
+//     int a5 && < a5 => 1, // Error.
+//                 ^
 //
 import self as self;
 import "dart:core" as core;
+import "dart:collection" as col;
 
-static method test8() → dynamic {
-  core::int x8 = 0;
-  core::List<core::int> list8 = core::_GrowableList::•<core::int>(0);
-  list8.{core::List::addAll}(invalid-expression "pkg/front_end/testcases/patterns/issue51971_2.dart:66:23: Error: Not a constant expression.
-  list8.addAll(const [x8]);
-                      ^^"){(core::Iterable<core::int>) → void};
-  return list8;
+static method test1(dynamic x1) → dynamic {
+  {
+    hoisted core::int a1;
+    final synthesized dynamic #0#0 = x1;
+    final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t2 = a1 = #0#0{core::int} in true)) {
+      return a1;
+    }
+    else {
+      hoisted core::int a1;
+      final synthesized dynamic #1#0 = x1;
+      final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+      if(#1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+        return a1;
+      }
+      else {
+        return null;
+      }
+    }
+  }
+}
+static method test2(dynamic x2) → dynamic {
+  #L1:
+  {
+    final synthesized dynamic #0#0 = x2;
+    {
+      lowered hoisted core::int a2#case#0;
+      lowered hoisted core::String a2#case#1;
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t5 = a2#case#0 = #0#0{core::int} in true) || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t6 = a2#case#1 = #0#0{core::String} in true)) {
+        {
+          return 1;
+        }
+      }
+    }
+    {
+      {
+        {
+          return 0;
+        }
+      }
+    }
+  }
+}
+static method test3(dynamic x3) → dynamic {
+  #L2:
+  {
+    final synthesized dynamic #0#0 = x3;
+    final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    final const synthesized core::String #0#3 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    {
+      lowered hoisted core::int a3#case#0;
+      lowered hoisted core::String a3#case#1;
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") {
+        {
+          return 1;
+        }
+      }
+    }
+    {
+      {
+        {
+          return 0;
+        }
+      }
+    }
+  }
+}
+static method test4(dynamic x4) → dynamic {
+  #L3:
+  {
+    final synthesized dynamic #0#0 = x4;
+    final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    final const synthesized core::String #0#3 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    {
+      lowered hoisted core::int a4#case#0;
+      lowered hoisted core::String a4#case#1;
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) {
+        {
+          return 1;
+        }
+      }
+    }
+    {
+      {
+        {
+          return 0;
+        }
+      }
+    }
+  }
+}
+static method test5(dynamic x5) → dynamic {
+  return block {
+    core::int #t11;
+    final synthesized dynamic #0#0 = x5;
+    final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    #L4:
+    {
+      {
+        hoisted core::int a5;
+        if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+          #t11 = 1;
+          break #L4;
+        }
+      }
+      {
+        if(true) {
+          #t11 = 0;
+          break #L4;
+        }
+      }
+    }
+  } =>#t11;
+}
+static method test6(dynamic x6) → dynamic {
+  return block {
+    final core::Set<core::int> #t13 = new col::_Set::•<core::int>();
+    hoisted core::int i6;
+    hoisted core::int n6;
+    {
+      final synthesized dynamic #0#0 = x6 as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<core::int>;
+      function ##0#6#initializer() → dynamic
+        return #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic};
+      late final synthesized dynamic #0#6 = ##0#6#initializer(){() → dynamic};
+      function ##0#7#initializer() → dynamic
+        return #0#0{core::List<dynamic>}.{core::List::[]}(1){(core::int) → dynamic};
+      late final synthesized dynamic #0#7 = ##0#7#initializer(){() → dynamic};
+      if(!(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (#0#6 is{ForNonNullableByDefault} core::int && (let final core::int #t14 = i6 = #0#6{core::int} in true)) && (#0#7 is{ForNonNullableByDefault} core::int && (let final core::int #t15 = n6 = #0#7{core::int} in true))))
+        throw new core::StateError::•("Pattern matching error");
+    }
+    final core::int #t16 = i6;
+    final core::int #t17 = n6;
+    for (core::int i6 = #t16, core::int n6 = #t17; i6.{core::num::<}(n6){(core::num) → core::bool}; i6 = i6.{core::num::+}(1){(core::num) → core::int})
+      #t13.{core::Set::add}{Invariant}(i6){(core::int) → core::bool};
+  } =>#t13;
+}
+static method test7(dynamic x7) → dynamic {
+  {
+    hoisted core::int i7;
+    hoisted core::int n7;
+    {
+      final synthesized dynamic #0#0 = x7 as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<core::int>;
+      function ##0#6#initializer() → dynamic
+        return #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic};
+      late final synthesized dynamic #0#6 = ##0#6#initializer(){() → dynamic};
+      function ##0#7#initializer() → dynamic
+        return #0#0{core::List<dynamic>}.{core::List::[]}(1){(core::int) → dynamic};
+      late final synthesized dynamic #0#7 = ##0#7#initializer(){() → dynamic};
+      if(!(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (#0#6 is{ForNonNullableByDefault} core::int && (let final core::int #t18 = i7 = #0#6{core::int} in true)) && (#0#7 is{ForNonNullableByDefault} core::int && (let final core::int #t19 = n7 = #0#7{core::int} in true))))
+        throw new core::StateError::•("Pattern matching error");
+    }
+    final core::int #t20 = i7;
+    final core::int #t21 = n7;
+    for (core::int i7 = #t20, core::int n7 = #t21; i7.{core::num::<}(n7){(core::num) → core::bool}; i7 = i7.{core::num::+}(1){(core::num) → core::int}) {
+      if(i7.{core::num::%}(3){(core::num) → core::int} =={core::num::==}{(core::Object) → core::bool} 0)
+        return i7;
+    }
+  }
+  return null;
+}
+
+constants  {
+  #C1 = 2
 }
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.expect
index 6a64fa0..e25b041 100644
--- a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.expect
+++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.expect
@@ -40,14 +40,14 @@
     hoisted core::int a1;
     final synthesized dynamic #0#0 = x1;
     final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
-    if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) {
+    if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) {
       return a1;
     }
     else {
       hoisted core::int a1;
       final synthesized dynamic #1#0 = x1;
       final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
-      if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+      if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
         return a1;
       }
       else {
@@ -87,7 +87,7 @@
     {
       lowered hoisted core::int a3#case#0;
       lowered hoisted core::String a3#case#1;
-      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") {
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") {
         {
           return 1;
         }
@@ -111,7 +111,7 @@
     {
       lowered hoisted core::int a4#case#0;
       lowered hoisted core::String a4#case#1;
-      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) {
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) {
         {
           return 1;
         }
@@ -135,7 +135,7 @@
     {
       {
         hoisted core::int a5;
-        if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+        if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
           #t11 = 1;
           break #L4;
         }
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.modular.expect
index 6a64fa0..e25b041 100644
--- a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.modular.expect
@@ -40,14 +40,14 @@
     hoisted core::int a1;
     final synthesized dynamic #0#0 = x1;
     final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
-    if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) {
+    if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) {
       return a1;
     }
     else {
       hoisted core::int a1;
       final synthesized dynamic #1#0 = x1;
       final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
-      if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+      if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
         return a1;
       }
       else {
@@ -87,7 +87,7 @@
     {
       lowered hoisted core::int a3#case#0;
       lowered hoisted core::String a3#case#1;
-      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") {
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") {
         {
           return 1;
         }
@@ -111,7 +111,7 @@
     {
       lowered hoisted core::int a4#case#0;
       lowered hoisted core::String a4#case#1;
-      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) {
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) {
         {
           return 1;
         }
@@ -135,7 +135,7 @@
     {
       {
         hoisted core::int a5;
-        if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+        if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
           #t11 = 1;
           break #L4;
         }
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.transformed.expect
index fd24527..20b89de 100644
--- a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.transformed.expect
@@ -2,18 +2,201 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/patterns/issue51971_2.dart:66:23: Error: Not a constant expression.
-//   list8.addAll(const [x8]);
-//                       ^^
+// pkg/front_end/testcases/patterns/issue51971_2.dart:6:27: Error: Read of a non-const variable is not a constant expression.
+//   if (x1 case int a1 && < a1 || int a1) { // Error.
+//                           ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:8:44: Error: Read of a non-const variable is not a constant expression.
+//   } else if (x1 case int a1 || int a1 && < a1) { // Error.
+//                                            ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:27:22: Error: Read of a non-const variable is not a constant expression.
+//     case int a3 && < a3: // Error.
+//                      ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:28:26: Error: Read of a non-const variable is not a constant expression.
+//     case String a3 && == a3: // Error.
+//                          ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:37:22: Error: Read of a non-const variable is not a constant expression.
+//     case int a4 && < a4 when a4 > 0: // Error.
+//                      ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:38:26: Error: Read of a non-const variable is not a constant expression.
+//     case String a4 && == a4 when a4.startsWith("f"): // Error.
+//                          ^
+//
+// pkg/front_end/testcases/patterns/issue51971_2.dart:47:17: Error: Read of a non-const variable is not a constant expression.
+//     int a5 && < a5 => 1, // Error.
+//                 ^
 //
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
+import "dart:collection" as col;
 
-static method test8() → dynamic {
-  core::int x8 = 0;
-  core::List<core::int> list8 = core::_GrowableList::•<core::int>(0);
-  list8.{core::List::addAll}(invalid-expression "pkg/front_end/testcases/patterns/issue51971_2.dart:66:23: Error: Not a constant expression.
-  list8.addAll(const [x8]);
-                      ^^"){(core::Iterable<core::int>) → void};
-  return list8;
+static method test1(dynamic x1) → dynamic {
+  {
+    hoisted core::int a1;
+    final synthesized dynamic #0#0 = x1;
+    final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t2 = a1 = #0#0{core::int} in true)) {
+      return a1;
+    }
+    else {
+      hoisted core::int a1;
+      final synthesized dynamic #1#0 = x1;
+      final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+      if(#1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+        return a1;
+      }
+      else {
+        return null;
+      }
+    }
+  }
+}
+static method test2(dynamic x2) → dynamic {
+  #L1:
+  {
+    final synthesized dynamic #0#0 = x2;
+    {
+      lowered hoisted core::int a2#case#0;
+      lowered hoisted core::String a2#case#1;
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t5 = a2#case#0 = #0#0{core::int} in true) || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t6 = a2#case#1 = #0#0{core::String} in true)) {
+        {
+          return 1;
+        }
+      }
+    }
+    {
+      {
+        {
+          return 0;
+        }
+      }
+    }
+  }
+}
+static method test3(dynamic x3) → dynamic {
+  #L2:
+  {
+    final synthesized dynamic #0#0 = x3;
+    final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    final const synthesized core::String #0#3 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    {
+      lowered hoisted core::int a3#case#0;
+      lowered hoisted core::String a3#case#1;
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") {
+        {
+          return 1;
+        }
+      }
+    }
+    {
+      {
+        {
+          return 0;
+        }
+      }
+    }
+  }
+}
+static method test4(dynamic x4) → dynamic {
+  #L3:
+  {
+    final synthesized dynamic #0#0 = x4;
+    final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    final const synthesized core::String #0#3 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    {
+      lowered hoisted core::int a4#case#0;
+      lowered hoisted core::String a4#case#1;
+      if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) {
+        {
+          return 1;
+        }
+      }
+    }
+    {
+      {
+        {
+          return 0;
+        }
+      }
+    }
+  }
+}
+static method test5(dynamic x5) → dynamic {
+  return block {
+    core::int #t11;
+    final synthesized dynamic #0#0 = x5;
+    final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression.";
+    #L4:
+    {
+      {
+        hoisted core::int a5;
+        if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) {
+          #t11 = 1;
+          break #L4;
+        }
+      }
+      {
+        if(true) {
+          #t11 = 0;
+          break #L4;
+        }
+      }
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable type.");
+    }
+  } =>#t11;
+}
+static method test6(dynamic x6) → dynamic {
+  return block {
+    final core::Set<core::int> #t13 = new col::_Set::•<core::int>();
+    hoisted core::int i6;
+    hoisted core::int n6;
+    {
+      final synthesized dynamic #0#0 = x6 as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<core::int>;
+      function ##0#6#initializer() → dynamic
+        return #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic};
+      late final synthesized dynamic #0#6 = ##0#6#initializer(){() → dynamic};
+      function ##0#7#initializer() → dynamic
+        return #0#0{core::List<dynamic>}.{core::List::[]}(1){(core::int) → dynamic};
+      late final synthesized dynamic #0#7 = ##0#7#initializer(){() → dynamic};
+      if(!(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (#0#6 is{ForNonNullableByDefault} core::int && (let final core::int #t14 = i6 = #0#6{core::int} in true)) && (#0#7 is{ForNonNullableByDefault} core::int && (let final core::int #t15 = n6 = #0#7{core::int} in true))))
+        throw new core::StateError::•("Pattern matching error");
+    }
+    final core::int #t16 = i6;
+    final core::int #t17 = n6;
+    for (core::int i6 = #t16, core::int n6 = #t17; i6.{core::num::<}(n6){(core::num) → core::bool}; i6 = i6.{core::num::+}(1){(core::num) → core::int})
+      #t13.{core::Set::add}{Invariant}(i6){(core::int) → core::bool};
+  } =>#t13;
+}
+static method test7(dynamic x7) → dynamic {
+  {
+    hoisted core::int i7;
+    hoisted core::int n7;
+    {
+      final synthesized dynamic #0#0 = x7 as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<core::int>;
+      function ##0#6#initializer() → dynamic
+        return #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic};
+      late final synthesized dynamic #0#6 = ##0#6#initializer(){() → dynamic};
+      function ##0#7#initializer() → dynamic
+        return #0#0{core::List<dynamic>}.{core::List::[]}(1){(core::int) → dynamic};
+      late final synthesized dynamic #0#7 = ##0#7#initializer(){() → dynamic};
+      if(!(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (#0#6 is{ForNonNullableByDefault} core::int && (let final core::int #t18 = i7 = #0#6{core::int} in true)) && (#0#7 is{ForNonNullableByDefault} core::int && (let final core::int #t19 = n7 = #0#7{core::int} in true))))
+        throw new core::StateError::•("Pattern matching error");
+    }
+    final core::int #t20 = i7;
+    final core::int #t21 = n7;
+    for (core::int i7 = #t20, core::int n7 = #t21; i7.{core::num::<}(n7){(core::num) → core::bool}; i7 = i7.{core::num::+}(1){(core::num) → core::int}) {
+      if(i7.{core::num::%}(3){(core::num) → core::int} =={core::num::==}{(core::Object) → core::bool} 0)
+        return i7;
+    }
+  }
+  return null;
+}
+
+constants  {
+  #C1 = 2
 }