Ensure that assert statements promote properly in unreachable code.

Fixes #40009.

Bug: https://github.com/dart-lang/sdk/issues/40009
Change-Id: I96561a72b6ba8dd8b8b95a4d9827d195941ea038
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166760
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index fad64cc..f809b87 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -2729,6 +2729,7 @@
 
   @override
   void assert_begin() {
+    _current = _current.split();
     _stack.add(new _AssertContext<Variable, Type>(_current));
   }
 
@@ -2736,7 +2737,7 @@
   void assert_end() {
     _AssertContext<Variable, Type> context =
         _stack.removeLast() as _AssertContext<Variable, Type>;
-    _current = _join(context._previous, context._conditionInfo.ifTrue);
+    _current = _merge(context._previous, context._conditionInfo.ifTrue);
   }
 
   @override
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
index 354b5bf..21f9263 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
@@ -40,6 +40,64 @@
   }
 }
 
+assertAlwaysThrows(Object o, Object p, bool Function(Object, Object) f) {
+  if (o is! int) return;
+  return;
+  assert(f(o = p, throw 'x'));
+  /*int*/ o;
+}
+
+class AssertAlwaysThrows_Constructor {
+  Object a;
+  Object b;
+
+  AssertAlwaysThrows_Constructor(
+      Object o, Object p, bool Function(Object, Object) f)
+      : a = o is int ? true : throw 'x',
+        b = throw 'x',
+        assert(f(o = p, throw 'x')) {
+    /*int*/ o;
+  }
+}
+
+assertFailsButMessageRepromotes(Object? o) {
+  if (o is! int) return;
+  return;
+  assert((o = null) != null, o is int ? 'ok' : throw 'x');
+  /*int*/ o;
+}
+
+class AssertFailsButMessageRepromotes_Constructor {
+  Object a;
+  Object b;
+
+  AssertFailsButMessageRepromotes_Constructor(Object? o)
+      : a = o is int ? true : throw 'x',
+        b = throw 'x',
+        assert((o = null) != null, o is int ? 'ok' : throw 'x') {
+    /*int*/ o;
+  }
+}
+
+assertMessageDepromotesButAlwaysThrows(Object o, Object p, bool b) {
+  if (o is! int) return;
+  return;
+  assert(b, throw (o = p));
+  /*int*/ o;
+}
+
+class AssertMessageDepromotesButAlwaysThrows {
+  Object a;
+  Object b;
+
+  AssertMessageDepromotesButAlwaysThrows(Object o, Object p, bool b)
+      : a = o is int ? true : throw 'x',
+        b = throw 'x',
+        assert(b, throw (o = p)) {
+    /*int*/ o;
+  }
+}
+
 conditionalIs(Object o) {
   return;
   o is int ? null : throw 'bad';