[sound flow analysis] Language tests.

The tests that don't end in `_disabled_test.dart` exercise all the new
behaviors introduced with the `sound-flow-analysis` feature. The tests
that _do_ end in `_disabled_test.dart` verify that when the language
version is 3.8, the old behavior of flow analysis is preserved.

For the sake of thoroughness, I've also elected to include tests for a
few behaviors that aren't new, just because they seem logically
related to the new behaviors (for example, in the tests for the `==`
and `!=` operator, I've included a test that `null == null` is known
to evaluate to `true`, even though this behavior existed even before
the `sound-flow-analysis` feature was implemented). These tests are
marked with the comment "(this behavior predates sound-flow-analysis)"
in the `_disabled_test.dart` files.

Bug: https://github.com/dart-lang/sdk/issues/60438
Change-Id: If2895355bb1a2eeb2415a5a1012d73ae87c244dd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/423040
Reviewed-by: Erik Ernst <eernst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/tests/language/sound_flow_analysis/equality_comparisons_disabled_test.dart b/tests/language/sound_flow_analysis/equality_comparisons_disabled_test.dart
new file mode 100644
index 0000000..6d9083f
--- /dev/null
+++ b/tests/language/sound_flow_analysis/equality_comparisons_disabled_test.dart
@@ -0,0 +1,631 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of equality comparisons (binary expressions using
+// `==` or `!=`) when `sound-flow-analysis` is disabled.
+
+// @dart = 3.8
+
+import '../static_type_helper.dart';
+
+// `<nonNullable> == <Null>` is not known to evaluate to `false`.
+testNonNullableEqualsNull({
+  required int intValue,
+  required int Function() intFunction,
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // <var> == null
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intValue == null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> == <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intValue == nullValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> == <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intValue == nullFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> == null
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intFunction() == null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> == <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intFunction() == nullValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> == <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intFunction() == nullFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<Null> == <nonNullable>` is not known to evaluate to `false`.
+testNullEqualsNonNullable({
+  required int intValue,
+  required int Function() intFunction,
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null == <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null == intValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> == <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue == intValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> == <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() == intValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // null == <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null == intFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> == <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue == intFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> == <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() == intFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable> != <Null>` is not known to evaluate to `true`.
+testNonNullableNotEqualsNull({
+  required int intValue,
+  required int Function() intFunction,
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // <var> != null
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intValue != null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> != <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intValue != nullValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> != <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intValue != nullFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> != null
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intFunction() != null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> != <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intFunction() != nullValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> != <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intFunction() != nullFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<Null> != <nonNullable>` is not known to evaluate to `true`.
+testNullNotEqualsNonNullable({
+  required int intValue,
+  required int Function() intFunction,
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null != <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null != intValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> != <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue != intValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> != <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() != intValue) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // null != <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null != intFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> != <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue != intFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> != <expr>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() != intFunction()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<Null> == <Null>` is known to evaluate to `true`.
+// (this behavior predates sound-flow-analysis)
+testNullEqualsNull({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null == null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null == null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null == nullValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null == nullFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue == null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue == nullValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue == nullFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() == null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() == nullValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() == nullFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<Null> != <Null>` is known to evaluate to `false`.
+// (this behavior predates sound-flow-analysis)
+testNullNotEqualsNull({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null != null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null != null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null != nullValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null != nullFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue != null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue != nullValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue != nullFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() != null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() != nullValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() != nullFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testNonNullableEqualsNull(
+    intValue: 0,
+    intFunction: () => 0,
+    nullValue: null,
+    nullFunction: () => null,
+  );
+  testNullEqualsNonNullable(
+    intValue: 0,
+    intFunction: () => 0,
+    nullValue: null,
+    nullFunction: () => null,
+  );
+  testNonNullableNotEqualsNull(
+    intValue: 0,
+    intFunction: () => 0,
+    nullValue: null,
+    nullFunction: () => null,
+  );
+  testNullNotEqualsNonNullable(
+    intValue: 0,
+    intFunction: () => 0,
+    nullValue: null,
+    nullFunction: () => null,
+  );
+  testNullEqualsNull(nullValue: null, nullFunction: () => null);
+  testNullNotEqualsNull(nullValue: null, nullFunction: () => null);
+}
diff --git a/tests/language/sound_flow_analysis/equality_comparisons_test.dart b/tests/language/sound_flow_analysis/equality_comparisons_test.dart
new file mode 100644
index 0000000..3734dc5
--- /dev/null
+++ b/tests/language/sound_flow_analysis/equality_comparisons_test.dart
@@ -0,0 +1,629 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of equality comparisons (binary expressions using
+// `==` or `!=`) when `sound-flow-analysis` is enabled.
+
+// SharedOptions=--enable-experiment=sound-flow-analysis
+
+import '../static_type_helper.dart';
+
+// `<nonNullable> == <Null>` is known to evaluate to `false`.
+testNonNullableEqualsNull({
+  required int intValue,
+  required int Function() intFunction,
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // <var> == null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intValue == null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intValue == nullValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intValue == nullFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intFunction() == null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intFunction() == nullValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intFunction() == nullFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<Null> == <nonNullable>` is known to evaluate to `false`.
+testNullEqualsNonNullable({
+  required int intValue,
+  required int Function() intFunction,
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null == intValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue == intValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() == intValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null == intFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue == intFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() == intFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable> != <Null>` is known to evaluate to `true`.
+testNonNullableNotEqualsNull({
+  required int intValue,
+  required int Function() intFunction,
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // <var> != null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intValue != null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intValue != nullValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intValue != nullFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intFunction() != null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intFunction() != nullValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intFunction() != nullFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<Null> != <nonNullable>` is known to evaluate to `true`.
+testNullNotEqualsNonNullable({
+  required int intValue,
+  required int Function() intFunction,
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null != intValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue != intValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() != intValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null != intFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue != intFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() != intFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<Null> == <Null>` is known to evaluate to `true`.
+testNullEqualsNull({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null == null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null == null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null == nullValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null == nullFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue == null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue == nullValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue == nullFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() == null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() == nullValue) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> == <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() == nullFunction()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<Null> != <Null>` is known to evaluate to `false`.
+testNullNotEqualsNull({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null != null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null != null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null != nullValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null != nullFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue != null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue != nullValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue != nullFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() != null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() != nullValue) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> != <expr>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() != nullFunction()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testNonNullableEqualsNull(
+    intValue: 0,
+    intFunction: () => 0,
+    nullValue: null,
+    nullFunction: () => null,
+  );
+  testNullEqualsNonNullable(
+    intValue: 0,
+    intFunction: () => 0,
+    nullValue: null,
+    nullFunction: () => null,
+  );
+  testNonNullableNotEqualsNull(
+    intValue: 0,
+    intFunction: () => 0,
+    nullValue: null,
+    nullFunction: () => null,
+  );
+  testNullNotEqualsNonNullable(
+    intValue: 0,
+    intFunction: () => 0,
+    nullValue: null,
+    nullFunction: () => null,
+  );
+  testNullEqualsNull(nullValue: null, nullFunction: () => null);
+  testNullNotEqualsNull(nullValue: null, nullFunction: () => null);
+}
diff --git a/tests/language/sound_flow_analysis/if_null_disabled_test.dart b/tests/language/sound_flow_analysis/if_null_disabled_test.dart
new file mode 100644
index 0000000..bcb9f73
--- /dev/null
+++ b/tests/language/sound_flow_analysis/if_null_disabled_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of if-null expressions (expressions involving `??`)
+// when `sound-flow-analysis` is disabled.
+
+// @dart = 3.8
+
+// ignore_for_file: dead_null_aware_expression
+
+import '../static_type_helper.dart';
+
+// `<nonNullable> ?? <expr>` is not known to skip <expr>.
+testIfNull({required int intValue, required int Function() intFunction}) {
+  {
+    // <var> ?? <expr>
+    int? shouldBeDemoted = 0;
+    intValue ?? (shouldBeDemoted = null, 0).$2;
+    shouldBeDemoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> ?? <expr>
+    int? shouldBeDemoted = 0;
+    intFunction() ?? (shouldBeDemoted = null, 0).$2;
+    shouldBeDemoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable> ??= <expr>` is not known to skip <expr>.
+testIfNullAssign({required int intValue, required List<int> listOfIntValue}) {
+  {
+    // <var> ??= <expr>
+    int? shouldBeDemoted = 0;
+    intValue ??= (shouldBeDemoted = null, 0).$2;
+    shouldBeDemoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <promotedVar> ??= <expr>
+    int? nullableIntValue = 0; // promote to `int`
+    int? shouldBeDemoted = 0;
+    nullableIntValue ??= (shouldBeDemoted = null, 0).$2;
+    shouldBeDemoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <property> ??= <expr>
+    int? shouldBeDemoted = 0;
+    listOfIntValue.first ??= (shouldBeDemoted = null, 0).$2;
+    shouldBeDemoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <indexOperation> ??= <expr>
+    int? shouldBeDemoted = 0;
+    listOfIntValue[0] ??= (shouldBeDemoted = null, 0).$2;
+    shouldBeDemoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  testIfNull(intValue: 0, intFunction: () => 0);
+  testIfNullAssign(intValue: 0, listOfIntValue: [0]);
+}
diff --git a/tests/language/sound_flow_analysis/if_null_test.dart b/tests/language/sound_flow_analysis/if_null_test.dart
new file mode 100644
index 0000000..1534055
--- /dev/null
+++ b/tests/language/sound_flow_analysis/if_null_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of if-null expressions (expressions involving `??`)
+// when `sound-flow-analysis` is enabled.
+
+// SharedOptions=--enable-experiment=sound-flow-analysis
+
+// ignore_for_file: dead_null_aware_expression
+
+import '../static_type_helper.dart';
+
+// `<nonNullable> ?? <expr>` is known to skip <expr>.
+testIfNull({required int intValue, required int Function() intFunction}) {
+  {
+    // <var> ?? <expr>
+    int? shouldNotBeDemoted = 0;
+    intValue ?? (shouldNotBeDemoted = null, 0).$2;
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> ?? <expr>
+    int? shouldNotBeDemoted = 0;
+    intFunction() ?? (shouldNotBeDemoted = null, 0).$2;
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable> ??= <expr>` is known to skip <expr>.
+testIfNullAssign({required int intValue, required List<int> listOfIntValue}) {
+  {
+    // <var> ??= <expr>
+    int? shouldNotBeDemoted = 0;
+    intValue ??= (shouldNotBeDemoted = null, 0).$2;
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <promotedVar> ??= <expr>
+    int? nullableIntValue = 0; // promote to `int`
+    int? shouldNotBeDemoted = 0;
+    nullableIntValue ??= (shouldNotBeDemoted = null, 0).$2;
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <property> ??= <expr>
+    int? shouldNotBeDemoted = 0;
+    listOfIntValue.first ??= (shouldNotBeDemoted = null, 0).$2;
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <indexOperation> ??= <expr>
+    int? shouldNotBeDemoted = 0;
+    listOfIntValue[0] ??= (shouldNotBeDemoted = null, 0).$2;
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testIfNull(intValue: 0, intFunction: () => 0);
+  testIfNullAssign(intValue: 0, listOfIntValue: [0]);
+}
diff --git a/tests/language/sound_flow_analysis/null_aware_access_disabled_test.dart b/tests/language/sound_flow_analysis/null_aware_access_disabled_test.dart
new file mode 100644
index 0000000..365dbb9
--- /dev/null
+++ b/tests/language/sound_flow_analysis/null_aware_access_disabled_test.dart
@@ -0,0 +1,174 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of null aware accesses (expressions involving `?.`)
+// when `sound-flow-analysis` is disabled.
+
+// @dart = 3.8
+
+// ignore_for_file: invalid_null_aware_operator
+
+import '../static_type_helper.dart';
+
+// `<nonNullable>?.bitLength.gcd(<expr>)` is not known to invoke <expr>.
+testProperty({required int intValue, required int Function() intFunction}) {
+  {
+    // <var>?.bitLength.gcd(<expr>)
+    int? shouldNotBePromoted;
+    intValue?.bitLength.gcd(shouldNotBePromoted = 0);
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr>?.bitLength.gcd(<expr>)
+    int? shouldNotBePromoted;
+    intFunction()?.bitLength.gcd(shouldNotBePromoted = 0);
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable>?.gcd(<expr>)` is not known to invoke <expr>.
+testCall({required int intValue, required int Function() intFunction}) {
+  {
+    // <var>?.gcd(<expr>)
+    int? shouldNotBePromoted;
+    intValue?.gcd(shouldNotBePromoted = 0);
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr>?.gcd(<expr>)
+    int? shouldNotBePromoted;
+    intFunction()?.gcd(shouldNotBePromoted = 0);
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable>?[<expr>]` is not known to invoke <expr>.
+testIndexGet({
+  required List<int> listOfIntValue,
+  required List<int> Function() listOfIntFunction,
+}) {
+  {
+    // <var>?[<expr>]
+    int? shouldNotBePromoted;
+    listOfIntValue?[shouldNotBePromoted = 0];
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr>?[<expr>]
+    int? shouldNotBePromoted;
+    listOfIntFunction()?[shouldNotBePromoted = 0];
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable>?[<expr>] = 0` is not known to invoke <expr>.
+testIndexSet({
+  required List<int> listOfIntValue,
+  required List<int> Function() listOfIntFunction,
+}) {
+  {
+    // <var>?[<expr>] = 0
+    int? shouldNotBePromoted;
+    listOfIntValue?[shouldNotBePromoted = 0] = 0;
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr>?[<expr>] = 0
+    int? shouldNotBePromoted;
+    listOfIntFunction()?[shouldNotBePromoted = 0] = 0;
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable>?..bitLength.gcd(<expr>)` is not known to invoke <expr>.
+testCascadedProperty({
+  required int intValue,
+  required int Function() intFunction,
+}) {
+  {
+    // <var>?..bitLength.gcd(<expr>)
+    int? shouldNotBePromoted;
+    intValue?..bitLength.gcd(shouldNotBePromoted = 0);
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr>?..bitLength.gcd(<expr>)
+    int? shouldNotBePromoted;
+    intFunction()?..bitLength.gcd(shouldNotBePromoted = 0);
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable>?..gcd(<expr>)` is not known to invoke <expr>.
+testCascadedCall({required int intValue, required int Function() intFunction}) {
+  {
+    // <var>?..gcd(<expr>)
+    int? shouldNotBePromoted;
+    intValue?..gcd(shouldNotBePromoted = 0);
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr>?..gcd(<expr>)
+    int? shouldNotBePromoted;
+    intFunction()?..gcd(shouldNotBePromoted = 0);
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable>?..[<expr>]` is not known to invoke <expr>.
+testCascadedIndexGet({
+  required List<int> listOfIntValue,
+  required List<int> Function() listOfIntFunction,
+}) {
+  {
+    // <var>?..[<expr>]
+    int? shouldNotBePromoted;
+    listOfIntValue?..[shouldNotBePromoted = 0];
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr>?..[<expr>]
+    int? shouldNotBePromoted;
+    listOfIntFunction()?..[shouldNotBePromoted = 0];
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable>?..[<expr>] = 0` is not known to invoke <expr>.
+testCascadedIndexSet({
+  required List<int> listOfIntValue,
+  required List<int> Function() listOfIntFunction,
+}) {
+  {
+    // <var>?..[<expr>] = 0
+    int? shouldNotBePromoted;
+    listOfIntValue?..[shouldNotBePromoted = 0] = 0;
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr>?..[<expr>] = 0
+    int? shouldNotBePromoted;
+    listOfIntFunction()?..[shouldNotBePromoted = 0] = 0;
+    shouldNotBePromoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  testProperty(intValue: 0, intFunction: () => 0);
+  testCall(intValue: 0, intFunction: () => 0);
+  testIndexGet(listOfIntValue: [0], listOfIntFunction: () => [0]);
+  testIndexSet(listOfIntValue: [0], listOfIntFunction: () => [0]);
+  testCascadedProperty(intValue: 0, intFunction: () => 0);
+  testCascadedCall(intValue: 0, intFunction: () => 0);
+  testCascadedIndexGet(listOfIntValue: [0], listOfIntFunction: () => [0]);
+  testCascadedIndexSet(listOfIntValue: [0], listOfIntFunction: () => [0]);
+}
diff --git a/tests/language/sound_flow_analysis/null_aware_access_test.dart b/tests/language/sound_flow_analysis/null_aware_access_test.dart
new file mode 100644
index 0000000..16778d8
--- /dev/null
+++ b/tests/language/sound_flow_analysis/null_aware_access_test.dart
@@ -0,0 +1,174 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of null aware accesses (expressions involving `?.`)
+// when `sound-flow-analysis` is enabled.
+
+// SharedOptions=--enable-experiment=sound-flow-analysis
+
+// ignore_for_file: invalid_null_aware_operator
+
+import '../static_type_helper.dart';
+
+// `<nonNullable>?.bitLength.gcd(<expr>)` is known to invoke <expr>.
+testProperty({required int intValue, required int Function() intFunction}) {
+  {
+    // <var>?.bitLength.gcd(<expr>)
+    int? shouldBePromoted;
+    intValue?.bitLength.gcd(shouldBePromoted = 0);
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr>?.bitLength.gcd(<expr>)
+    int? shouldBePromoted;
+    intFunction()?.bitLength.gcd(shouldBePromoted = 0);
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>?.gcd(<expr>)` is known to invoke <expr>.
+testCall({required int intValue, required int Function() intFunction}) {
+  {
+    // <var>?.gcd(<expr>)
+    int? shouldBePromoted;
+    intValue?.gcd(shouldBePromoted = 0);
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr>?.gcd(<expr>)
+    int? shouldBePromoted;
+    intFunction()?.gcd(shouldBePromoted = 0);
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>?[<expr>]` is known to invoke <expr>.
+testIndexGet({
+  required List<int> listOfIntValue,
+  required List<int> Function() listOfIntFunction,
+}) {
+  {
+    // <var>?[<expr>]
+    int? shouldBePromoted;
+    listOfIntValue?[shouldBePromoted = 0];
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr>?[<expr>]
+    int? shouldBePromoted;
+    listOfIntFunction()?[shouldBePromoted = 0];
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>?[<expr>] = 0` is known to invoke <expr>.
+testIndexSet({
+  required List<int> listOfIntValue,
+  required List<int> Function() listOfIntFunction,
+}) {
+  {
+    // <var>?[<expr>] = 0
+    int? shouldBePromoted;
+    listOfIntValue?[shouldBePromoted = 0] = 0;
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr>?[<expr>] = 0
+    int? shouldBePromoted;
+    listOfIntFunction()?[shouldBePromoted = 0] = 0;
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>?..bitLength.gcd(<expr>)` is known to invoke <expr>.
+testCascadedProperty({
+  required int intValue,
+  required int Function() intFunction,
+}) {
+  {
+    // <var>?..bitLength.gcd(<expr>)
+    int? shouldBePromoted;
+    intValue?..bitLength.gcd(shouldBePromoted = 0);
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr>?..bitLength.gcd(<expr>)
+    int? shouldBePromoted;
+    intFunction()?..bitLength.gcd(shouldBePromoted = 0);
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>?..gcd(<expr>)` is known to invoke <expr>.
+testCascadedCall({required int intValue, required int Function() intFunction}) {
+  {
+    // <var>?..gcd(<expr>)
+    int? shouldBePromoted;
+    intValue?..gcd(shouldBePromoted = 0);
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr>?..gcd(<expr>)
+    int? shouldBePromoted;
+    intFunction()?..gcd(shouldBePromoted = 0);
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>?..[<expr>]` is known to invoke <expr>.
+testCascadedIndexGet({
+  required List<int> listOfIntValue,
+  required List<int> Function() listOfIntFunction,
+}) {
+  {
+    // <var>?..[<expr>]
+    int? shouldBePromoted;
+    listOfIntValue?..[shouldBePromoted = 0];
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr>?..[<expr>]
+    int? shouldBePromoted;
+    listOfIntFunction()?..[shouldBePromoted = 0];
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>?..[<expr>] = 0` is known to invoke <expr>.
+testCascadedIndexSet({
+  required List<int> listOfIntValue,
+  required List<int> Function() listOfIntFunction,
+}) {
+  {
+    // <var>?..[<expr>] = 0
+    int? shouldBePromoted;
+    listOfIntValue?..[shouldBePromoted = 0] = 0;
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr>?..[<expr>] = 0
+    int? shouldBePromoted;
+    listOfIntFunction()?..[shouldBePromoted = 0] = 0;
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testProperty(intValue: 0, intFunction: () => 0);
+  testCall(intValue: 0, intFunction: () => 0);
+  testIndexGet(listOfIntValue: [0], listOfIntFunction: () => [0]);
+  testIndexSet(listOfIntValue: [0], listOfIntFunction: () => [0]);
+  testCascadedProperty(intValue: 0, intFunction: () => 0);
+  testCascadedCall(intValue: 0, intFunction: () => 0);
+  testCascadedIndexGet(listOfIntValue: [0], listOfIntFunction: () => [0]);
+  testCascadedIndexSet(listOfIntValue: [0], listOfIntFunction: () => [0]);
+}
diff --git a/tests/language/sound_flow_analysis/null_aware_map_entry_disabled_test.dart b/tests/language/sound_flow_analysis/null_aware_map_entry_disabled_test.dart
new file mode 100644
index 0000000..6a9eba1
--- /dev/null
+++ b/tests/language/sound_flow_analysis/null_aware_map_entry_disabled_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of null-aware map entries when `sound-flow-analysis`
+// is disabled.
+
+// @dart = 3.8
+
+// ignore_for_file: invalid_null_aware_operator
+
+import '../static_type_helper.dart';
+
+// `{ ?<nonNullable>: <expr> }` is known to invoke <expr>.
+// (this behavior predates sound-flow-analysis)
+testNonNullable({required int intValue, required int Function() intFunction}) {
+  {
+    // { ?<var>: <expr> }
+    int? shouldBePromoted;
+    ({?intValue: shouldBePromoted = 0});
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // { ?<expr>: <expr> }
+    int? shouldBePromoted;
+    ({?intFunction(): shouldBePromoted = 0});
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `{ ?<Null>: <expr> }` is not known to skip <expr>.
+testNull({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // { ?null: <expr> }
+    int? shouldBeDemoted = 0;
+    ({?null: (shouldBeDemoted = null, 0).$2});
+    shouldBeDemoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // { ?<var>: <expr> }
+    int? shouldBeDemoted = 0;
+    ({?nullValue: (shouldBeDemoted = null, 0).$2});
+    shouldBeDemoted.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // { ?<expr>: <expr> }
+    int? shouldBeDemoted = 0;
+    ({?nullFunction(): (shouldBeDemoted = null, 0).$2});
+    shouldBeDemoted.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  testNonNullable(intValue: 0, intFunction: () => 0);
+  testNull(nullValue: null, nullFunction: () => null);
+}
diff --git a/tests/language/sound_flow_analysis/null_aware_map_entry_test.dart b/tests/language/sound_flow_analysis/null_aware_map_entry_test.dart
new file mode 100644
index 0000000..349ce18
--- /dev/null
+++ b/tests/language/sound_flow_analysis/null_aware_map_entry_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of null-aware map entries when `sound-flow-analysis`
+// is enabled.
+
+// SharedOptions=--enable-experiment=sound-flow-analysis
+
+// ignore_for_file: invalid_null_aware_operator
+
+import '../static_type_helper.dart';
+
+// `{ ?<nonNullable>: <expr> }` is known to invoke <expr>.
+testNonNullable({required int intValue, required int Function() intFunction}) {
+  {
+    // { ?<var>: <expr> }
+    int? shouldBePromoted;
+    ({?intValue: shouldBePromoted = 0});
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // { ?<expr>: <expr> }
+    int? shouldBePromoted;
+    ({?intFunction(): shouldBePromoted = 0});
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `{ ?<Null>: <expr> }` is known to skip <expr>.
+testNull({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // { ?null: <expr> }
+    int? shouldNotBeDemoted = 0;
+    ({?null: (shouldNotBeDemoted = null, 0).$2});
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // { ?<var>: <expr> }
+    int? shouldNotBeDemoted = 0;
+    ({?nullValue: (shouldNotBeDemoted = null, 0).$2});
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // { ?<expr>: <expr> }
+    int? shouldNotBeDemoted = 0;
+    ({?nullFunction(): (shouldNotBeDemoted = null, 0).$2});
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testNonNullable(intValue: 0, intFunction: () => 0);
+  testNull(nullValue: null, nullFunction: () => null);
+}
diff --git a/tests/language/sound_flow_analysis/pattern_matching_non_nullable_disabled_test.dart b/tests/language/sound_flow_analysis/pattern_matching_non_nullable_disabled_test.dart
new file mode 100644
index 0000000..83f00a2
--- /dev/null
+++ b/tests/language/sound_flow_analysis/pattern_matching_non_nullable_disabled_test.dart
@@ -0,0 +1,154 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of patterns that match a non-nullable scrutinee when
+// `sound-flow-analysis` is disabled.
+
+// @dart = 3.8
+
+// ignore_for_file: unnecessary_null_check_pattern
+
+import '../static_type_helper.dart';
+
+const Null null_ = null;
+
+// `<pattern>?` is not known to match a non-nullable expression.
+testNullCheck() {
+  {
+    // <nonNullable> case <pattern>?
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case _?) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable> <var>` is known to match a suitably typed non-nullable expression.
+// (this behavior predates sound-flow-analysis)
+testDeclaredVar() {
+  {
+    // <nonNullable> case <nonNullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case int i) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `[...]` is known to match a suitably typed non-nullable expression.
+// (this behavior predates sound-flow-analysis)
+testList() {
+  {
+    // [] case [...]
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if ([] case [...]) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>()` is known to match a suitably typed non-nullable expression.
+// (this behavior predates sound-flow-analysis)
+testObject() {
+  {
+    // <nonNullable> case <nonNullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case int()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `(<pattern>,)` is known to match a suitably typed non-nullable expression.
+// (this behavior predates sound-flow-analysis)
+testRecord() {
+  {
+    // (<expr>,) case (<pattern>,)
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if ((0,) case (_,)) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable> _` is known to match a suitably typed non-nullable expression.
+// (this behavior predates sound-flow-analysis)
+testWildcard() {
+  {
+    // <nonNullable> case <nonNullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case int _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `!= <Null>` is not known to match a non-nullable expression.
+testNotEqualNull() {
+  {
+    // <nonNullable> case != <null literal>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case != null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <nonNullable> case != <null const>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case != null_) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  testNullCheck();
+  testDeclaredVar();
+  testList();
+  testObject();
+  testRecord();
+  testWildcard();
+  testNotEqualNull();
+}
diff --git a/tests/language/sound_flow_analysis/pattern_matching_non_nullable_test.dart b/tests/language/sound_flow_analysis/pattern_matching_non_nullable_test.dart
new file mode 100644
index 0000000..937c526
--- /dev/null
+++ b/tests/language/sound_flow_analysis/pattern_matching_non_nullable_test.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of patterns that match a non-nullable scrutinee when
+// `sound-flow-analysis` is enabled.
+
+// SharedOptions=--enable-experiment=sound-flow-analysis
+
+// ignore_for_file: unnecessary_null_check_pattern
+
+import '../static_type_helper.dart';
+
+const Null null_ = null;
+
+// `<pattern>?` is known to match a non-nullable expression.
+testNullCheck() {
+  {
+    // <nonNullable> case <pattern>?
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case _?) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable> <var>` is known to match a suitably typed non-nullable expression.
+testDeclaredVar() {
+  {
+    // <nonNullable> case <nonNullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case int i) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `[...]` is known to match a suitably typed non-nullable expression.
+testList() {
+  {
+    // [] case [...]
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if ([] case [...]) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>()` is known to match a suitably typed non-nullable expression.
+testObject() {
+  {
+    // <nonNullable> case <nonNullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case int()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `(<pattern>,)` is known to match a suitably typed non-nullable expression.
+testRecord() {
+  {
+    // (<expr>,) case (<pattern>,)
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if ((0,) case (_,)) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable> _` is known to match a suitably typed non-nullable expression.
+testWildcard() {
+  {
+    // <nonNullable> case <nonNullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case int _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `!= <Null>` is known to match a non-nullable expression.
+testNotEqualNull() {
+  {
+    // <nonNullable> case != <null literal>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case != null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <nonNullable> case != <null const>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case != null_) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testNullCheck();
+  testDeclaredVar();
+  testList();
+  testObject();
+  testRecord();
+  testWildcard();
+  testNotEqualNull();
+}
diff --git a/tests/language/sound_flow_analysis/pattern_matching_null_disabled_test.dart b/tests/language/sound_flow_analysis/pattern_matching_null_disabled_test.dart
new file mode 100644
index 0000000..5331e95
--- /dev/null
+++ b/tests/language/sound_flow_analysis/pattern_matching_null_disabled_test.dart
@@ -0,0 +1,467 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of patterns that match a Null scrutinee when
+// `sound-flow-analysis` is disabled.
+
+// @dart = 3.8
+
+import '../static_type_helper.dart';
+
+typedef IntQuestion = int?;
+
+// `<pattern> as <nullable>` is known to match a null expression.
+// (this behavior predates sound-flow-analysis)
+testCast({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case _ as Null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case _ as int?) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case _ as IntQuestion) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case _ as Null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case _ as int?) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case _ as IntQuestion) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case _ as Null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case _ as int?) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case _ as IntQuestion) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nullable> <var>` is known to match a null expression.
+// (this behavior predates sound-flow-analysis)
+testDeclaredVar({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case Null v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case int? v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case IntQuestion v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case Null v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case int? v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case IntQuestion v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case Null v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case int? v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case IntQuestion v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nullable>()` is known to match a null expression.
+// (this behavior predates sound-flow-analysis)
+testObject({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case Null()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case IntQuestion()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case Null()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case IntQuestion()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case Null()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case IntQuestion()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nullable> _` is known to match a null expression.
+// (this behavior predates sound-flow-analysis)
+testWildcard({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case Null _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case int? _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case IntQuestion _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case Null _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case int? _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case IntQuestion _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case Null _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case int? _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case IntQuestion _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testCast(nullValue: null, nullFunction: () => null);
+  testDeclaredVar(nullValue: null, nullFunction: () => null);
+  testObject(nullValue: null, nullFunction: () => null);
+  testWildcard(nullValue: null, nullFunction: () => null);
+}
diff --git a/tests/language/sound_flow_analysis/pattern_matching_null_test.dart b/tests/language/sound_flow_analysis/pattern_matching_null_test.dart
new file mode 100644
index 0000000..1bb7eb9
--- /dev/null
+++ b/tests/language/sound_flow_analysis/pattern_matching_null_test.dart
@@ -0,0 +1,463 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of patterns that match a Null scrutinee when
+// `sound-flow-analysis` is enabled.
+
+// SharedOptions=--enable-experiment=sound-flow-analysis
+
+import '../static_type_helper.dart';
+
+typedef IntQuestion = int?;
+
+// `<pattern> as <nullable>` is known to match a null expression.
+testCast({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case _ as Null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case _ as int?) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case _ as IntQuestion) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case _ as Null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case _ as int?) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case _ as IntQuestion) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case _ as Null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case _ as int?) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <pattern> as <nullable>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case _ as IntQuestion) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nullable> <var>` is known to match a null expression.
+testDeclaredVar({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case Null v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case int? v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case IntQuestion v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case Null v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case int? v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case IntQuestion v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case Null v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case int? v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case IntQuestion v) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nullable>()` is known to match a null expression.
+testObject({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case Null()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case IntQuestion()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case Null()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case IntQuestion()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case Null()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case IntQuestion()) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nullable> _` is known to match a null expression.
+testWildcard({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case Null _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case int? _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // null case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case IntQuestion _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case Null _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case int? _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case IntQuestion _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case Null _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case int? _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case IntQuestion _) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testCast(nullValue: null, nullFunction: () => null);
+  testDeclaredVar(nullValue: null, nullFunction: () => null);
+  testObject(nullValue: null, nullFunction: () => null);
+  testWildcard(nullValue: null, nullFunction: () => null);
+}
diff --git a/tests/language/sound_flow_analysis/pattern_not_matching_non_nullable_disabled_test.dart b/tests/language/sound_flow_analysis/pattern_not_matching_non_nullable_disabled_test.dart
new file mode 100644
index 0000000..29edbb7
--- /dev/null
+++ b/tests/language/sound_flow_analysis/pattern_not_matching_non_nullable_disabled_test.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of patterns that fail to match a non-nullable
+// scrutinee when `sound-flow-analysis` is disabled.
+
+// @dart = 3.8
+
+import 'package:expect/expect.dart';
+
+import '../static_type_helper.dart';
+
+const Null null_ = null;
+
+// `<Null>` is not known to mismatch a non-nullable expression.
+testConstNull() {
+  {
+    // <nonNullable> case <null literal>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <nonNullable> case <null const>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case null_) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `Null <var>` is not known to mismatch a non-nullable expression.
+testDeclaredVar() {
+  {
+    // <nonNullable> case Null <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case Null n) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<pattern> as Null` is not known to throw when matching a non-nullable expression.
+testCast({required bool true_}) {
+  {
+    // <nonNullable> case _ as Null
+    Expect.throws(() {
+      int? shouldBeDemoted = 0;
+      if (true_) {
+        if (0 case _ as Null) {}
+        shouldBeDemoted = null; // Reachable
+      }
+      shouldBeDemoted.expectStaticType<Exactly<int?>>();
+    });
+  }
+}
+
+// `Null()` is not known to mismatch a non-nullable expression.
+testObject() {
+  {
+    // <nonNullable> case Null()
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case Null()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `Null _` is not known to mismatch a non-nullable expression.
+testWildcard() {
+  {
+    // <nonNullable> case Null _
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case Null _) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `== <Null>` is not known to mismatch a non-nullable expression.
+testEqualNull() {
+  {
+    // <nonNullable> case == <null literal>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case == null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <nonNullable> case == <null const>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (0 case == null_) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  testConstNull();
+  testDeclaredVar();
+  testCast(true_: true);
+  testObject();
+  testWildcard();
+  testEqualNull();
+}
diff --git a/tests/language/sound_flow_analysis/pattern_not_matching_non_nullable_test.dart b/tests/language/sound_flow_analysis/pattern_not_matching_non_nullable_test.dart
new file mode 100644
index 0000000..730cd85
--- /dev/null
+++ b/tests/language/sound_flow_analysis/pattern_not_matching_non_nullable_test.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of patterns that fail to match a non-nullable
+// scrutinee when `sound-flow-analysis` is enabled.
+
+// SharedOptions=--enable-experiment=sound-flow-analysis
+
+import 'package:expect/expect.dart';
+
+import '../static_type_helper.dart';
+
+const Null null_ = null;
+
+// `<Null>` is known to mismatch a non-nullable expression.
+testConstNull() {
+  {
+    // <nonNullable> case <null literal>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <nonNullable> case <null const>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case null_) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `Null <var>` is known to mismatch a non-nullable expression.
+testDeclaredVar() {
+  {
+    // <nonNullable> case Null <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case Null n) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<pattern> as Null` is known to throw when matching a non-nullable expression.
+testCast({required bool true_}) {
+  {
+    // <nonNullable> case _ as Null
+    Expect.throws(() {
+      int? shouldNotBeDemoted = 0;
+      if (true_) {
+        if (0 case _ as Null) {}
+        shouldNotBeDemoted = null; // Unreachable
+      }
+      shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    });
+  }
+}
+
+// `Null()` is known to mismatch a non-nullable expression.
+testObject() {
+  {
+    // <nonNullable> case Null()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case Null()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `Null _` is known to mismatch a non-nullable expression.
+testWildcard() {
+  {
+    // <nonNullable> case Null _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case Null _) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `== <Null>` is known to mismatch a non-nullable expression.
+testEqualNull() {
+  {
+    // <nonNullable> case == <null literal>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case == null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <nonNullable> case == <null const>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (0 case == null_) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testConstNull();
+  testDeclaredVar();
+  testCast(true_: true);
+  testObject();
+  testWildcard();
+  testEqualNull();
+}
diff --git a/tests/language/sound_flow_analysis/pattern_not_matching_null_disabled_test.dart b/tests/language/sound_flow_analysis/pattern_not_matching_null_disabled_test.dart
new file mode 100644
index 0000000..a1a389a
--- /dev/null
+++ b/tests/language/sound_flow_analysis/pattern_not_matching_null_disabled_test.dart
@@ -0,0 +1,274 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of patterns that fail to match a Null scrutinee when
+// `sound-flow-analysis` is disabled.
+
+// @dart = 3.8
+
+import '../static_type_helper.dart';
+
+// `<nonNullable> <var>` is not known to mismatch a null expression.
+testDeclaredVar({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null case <nonNullable> <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null case int i) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> case <nonNullable> <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue case int i) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> case <nonNullable> <var>
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() case int i) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `[...]` is not known to mismatch a null expression.
+testList({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case [...]
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null case [...]) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> case [...]
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue case [...]) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> case [...]
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() case [...]) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `{...}` is not known to mismatch a null expression.
+testMap({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case {...}
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null case {0: 0}) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> case {...}
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue case {0: 0}) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> case {...}
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() case {0: 0}) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable>()` is not known to mismatch a null expression.
+testObject({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <nonNullable>()
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null case int()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> case <nonNullable>()
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue case int()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> case <nonNullable>()
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() case int()) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `(<pattern>,)` is not known to mismatch a null expression.
+testRecord({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case (<pattern>,)
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null case (_,)) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> case (<pattern>,)
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue case (_,)) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> case (<pattern>,)
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() case (_,)) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable> _` is not known to mismatch a null expression.
+testWildcard({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <nonNullable> _
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null case int _) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> case <nonNullable> _
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue case int _) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> case <nonNullable> _
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() case int _) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  testDeclaredVar(nullValue: null, nullFunction: () => null);
+  testList(nullValue: null, nullFunction: () => null);
+  testMap(nullValue: null, nullFunction: () => null);
+  testObject(nullValue: null, nullFunction: () => null);
+  testRecord(nullValue: null, nullFunction: () => null);
+  testWildcard(nullValue: null, nullFunction: () => null);
+}
diff --git a/tests/language/sound_flow_analysis/pattern_not_matching_null_test.dart b/tests/language/sound_flow_analysis/pattern_not_matching_null_test.dart
new file mode 100644
index 0000000..6d6a419
--- /dev/null
+++ b/tests/language/sound_flow_analysis/pattern_not_matching_null_test.dart
@@ -0,0 +1,274 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of patterns that fail to match a Null scrutinee when
+// `sound-flow-analysis` is enabled.
+
+// SharedOptions=--enable-experiment=sound-flow-analysis
+
+import '../static_type_helper.dart';
+
+// `<nonNullable> <var>` is known to mismatch a null expression.
+testDeclaredVar({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null case <nonNullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case int i) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nonNullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case int i) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nonNullable> <var>
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case int i) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `[...]` is known to mismatch a null expression.
+testList({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case [...]
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case [...]) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case [...]
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case [...]) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case [...]
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case [...]) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `{...}` is known to mismatch a null expression.
+testMap({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case {...}
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case {0: 0}) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case {...}
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case {0: 0}) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case {...}
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case {0: 0}) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable>()` is known to mismatch a null expression.
+testObject({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <nonNullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case int()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nonNullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case int()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nonNullable>()
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case int()) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `(<pattern>,)` is known to mismatch a null expression.
+testRecord({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case (<pattern>,)
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case (_,)) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case (<pattern>,)
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case (_,)) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case (<pattern>,)
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case (_,)) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable> _` is known to mismatch a null expression.
+testWildcard({required Null nullValue, required Null Function() nullFunction}) {
+  {
+    // null case <nonNullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null case int _) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> case <nonNullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue case int _) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> case <nonNullable> _
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() case int _) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testDeclaredVar(nullValue: null, nullFunction: () => null);
+  testList(nullValue: null, nullFunction: () => null);
+  testMap(nullValue: null, nullFunction: () => null);
+  testObject(nullValue: null, nullFunction: () => null);
+  testRecord(nullValue: null, nullFunction: () => null);
+  testWildcard(nullValue: null, nullFunction: () => null);
+}
diff --git a/tests/language/sound_flow_analysis/type_tests_disabled_test.dart b/tests/language/sound_flow_analysis/type_tests_disabled_test.dart
new file mode 100644
index 0000000..53ef2fd
--- /dev/null
+++ b/tests/language/sound_flow_analysis/type_tests_disabled_test.dart
@@ -0,0 +1,249 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of type tests (`is` and `as` expressions) when
+// `sound-flow-analysis` is disabled.
+
+// @dart = 3.8
+
+import 'package:expect/expect.dart';
+
+import '../static_type_helper.dart';
+
+// `<nonNullable> as Null` is not known to throw an exception.
+testNonNullableAsNull({
+  required int intValue,
+  required int Function() intFunction,
+  required bool true_,
+}) {
+  {
+    // <var> as Null
+    Expect.throws(() {
+      int? shouldBeDemoted = 0;
+      if (true_) {
+        intValue as Null;
+        shouldBeDemoted = null; // Reachable
+      }
+      shouldBeDemoted.expectStaticType<Exactly<int?>>();
+    });
+  }
+
+  {
+    // <expr> as Null
+    Expect.throws(() {
+      int? shouldBeDemoted = 0;
+      if (true_) {
+        intFunction() as Null;
+        shouldBeDemoted = null; // Reachable
+      }
+      shouldBeDemoted.expectStaticType<Exactly<int?>>();
+    });
+  }
+}
+
+// `<nonNullable> is Null` is not known to evaluate to `false`.
+testNonNullableIsNull({
+  required int intValue,
+  required int Function() intFunction,
+}) {
+  {
+    // <var> is Null
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intValue is Null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> is Null
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intFunction() is Null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<nonNullable> is! Null` is not known to evaluate to `true`.
+testNonNullableIsNotNull({
+  required int intValue,
+  required int Function() intFunction,
+}) {
+  {
+    // <var> is! Null
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intValue is! Null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> is! Null
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (intFunction() is! Null) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<Null> as <nonNullable>` is not known to throw an exception.
+testNullAsNonNullable({
+  required Null nullValue,
+  required Null Function() nullFunction,
+  required bool true_,
+}) {
+  {
+    // null as int
+    Expect.throws(() {
+      int? shouldBeDemoted = 0;
+      if (true_) {
+        null as int;
+        shouldBeDemoted = null; // Reachable
+      }
+      shouldBeDemoted.expectStaticType<Exactly<int?>>();
+    });
+  }
+
+  {
+    // <var> as int
+    Expect.throws(() {
+      int? shouldBeDemoted = 0;
+      if (true_) {
+        nullValue as int;
+        shouldBeDemoted = null; // Reachable
+      }
+      shouldBeDemoted.expectStaticType<Exactly<int?>>();
+    });
+  }
+
+  {
+    // <expr> as int
+    Expect.throws(() {
+      int? shouldBeDemoted = 0;
+      if (true_) {
+        nullFunction() as int;
+        shouldBeDemoted = null; // Reachable
+      }
+      shouldBeDemoted.expectStaticType<Exactly<int?>>();
+    });
+  }
+}
+
+// `<Null> is <nonNullable>` is not known to evaluate to `false`.
+testNullIsNonNullable({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null is int
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null is int) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> is int
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue is int) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> is int
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() is int) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+// `<Null> is! <nonNullable>` is not known to evaluate to `true`.
+testNullIsNotNonNullable({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null is! int
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (null is! int) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <var> is! int
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullValue is! int) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+
+  {
+    // <expr> is! int
+    int? shouldBeDemoted1 = 0;
+    int? shouldBeDemoted2 = 0;
+    if (nullFunction() is! int) {
+      shouldBeDemoted1 = null;
+    } else {
+      shouldBeDemoted2 = null;
+    }
+    shouldBeDemoted1.expectStaticType<Exactly<int?>>();
+    shouldBeDemoted2.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  testNonNullableAsNull(intValue: 0, intFunction: () => 0, true_: true);
+  testNonNullableIsNull(intValue: 0, intFunction: () => 0);
+  testNonNullableIsNotNull(intValue: 0, intFunction: () => 0);
+  testNullAsNonNullable(nullValue: null, nullFunction: () => null, true_: true);
+  testNullIsNonNullable(nullValue: null, nullFunction: () => null);
+  testNullIsNotNonNullable(nullValue: null, nullFunction: () => null);
+}
diff --git a/tests/language/sound_flow_analysis/type_tests_test.dart b/tests/language/sound_flow_analysis/type_tests_test.dart
new file mode 100644
index 0000000..76d2240
--- /dev/null
+++ b/tests/language/sound_flow_analysis/type_tests_test.dart
@@ -0,0 +1,249 @@
+// Copyright (c) 2025, 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.
+
+// Exercises flow analysis of type tests (`is` and `as` expressions) when
+// `sound-flow-analysis` is enabled.
+
+// SharedOptions=--enable-experiment=sound-flow-analysis
+
+import 'package:expect/expect.dart';
+
+import '../static_type_helper.dart';
+
+// `<nonNullable> as Null` is known to throw an exception.
+testNonNullableAsNull({
+  required int intValue,
+  required int Function() intFunction,
+  required bool true_,
+}) {
+  {
+    // <var> as Null
+    Expect.throws(() {
+      int? shouldNotBeDemoted = 0;
+      if (true_) {
+        intValue as Null;
+        shouldNotBeDemoted = null; // Unreachable
+      }
+      shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    });
+  }
+
+  {
+    // <expr> as Null
+    Expect.throws(() {
+      int? shouldNotBeDemoted = 0;
+      if (true_) {
+        intFunction() as Null;
+        shouldNotBeDemoted = null; // Unreachable
+      }
+      shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    });
+  }
+}
+
+// `<nonNullable> is Null` is known to evaluate to `false`.
+testNonNullableIsNull({
+  required int intValue,
+  required int Function() intFunction,
+}) {
+  {
+    // <var> is Null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intValue is Null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> is Null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intFunction() is Null) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<nonNullable> is! Null` is known to evaluate to `true`.
+testNonNullableIsNotNull({
+  required int intValue,
+  required int Function() intFunction,
+}) {
+  {
+    // <var> is! Null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intValue is! Null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> is! Null
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (intFunction() is! Null) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<Null> as <nonNullable>` is known to throw an exception.
+testNullAsNonNullable({
+  required Null nullValue,
+  required Null Function() nullFunction,
+  required bool true_,
+}) {
+  {
+    // null as int
+    Expect.throws(() {
+      int? shouldNotBeDemoted = 0;
+      if (true_) {
+        null as int;
+        shouldNotBeDemoted = null; // Unreachable
+      }
+      shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    });
+  }
+
+  {
+    // <var> as int
+    Expect.throws(() {
+      int? shouldNotBeDemoted = 0;
+      if (true_) {
+        nullValue as int;
+        shouldNotBeDemoted = null; // Unreachable
+      }
+      shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    });
+  }
+
+  {
+    // <expr> as int
+    Expect.throws(() {
+      int? shouldNotBeDemoted = 0;
+      if (true_) {
+        nullFunction() as int;
+        shouldNotBeDemoted = null; // Unreachable
+      }
+      shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    });
+  }
+}
+
+// `<Null> is <nonNullable>` is known to evaluate to `false`.
+testNullIsNonNullable({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null is int
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null is int) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> is int
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue is int) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> is int
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() is int) {
+      shouldNotBeDemoted = null; // Unreachable
+    } else {
+      shouldBePromoted = 0; // Reachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+// `<Null> is! <nonNullable>` is known to evaluate to `true`.
+testNullIsNotNonNullable({
+  required Null nullValue,
+  required Null Function() nullFunction,
+}) {
+  {
+    // null is! int
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (null is! int) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <var> is! int
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullValue is! int) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+
+  {
+    // <expr> is! int
+    int? shouldNotBeDemoted = 0;
+    int? shouldBePromoted;
+    if (nullFunction() is! int) {
+      shouldBePromoted = 0; // Reachable
+    } else {
+      shouldNotBeDemoted = null; // Unreachable
+    }
+    shouldNotBeDemoted.expectStaticType<Exactly<int>>();
+    shouldBePromoted.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  testNonNullableAsNull(intValue: 0, intFunction: () => 0, true_: true);
+  testNonNullableIsNull(intValue: 0, intFunction: () => 0);
+  testNonNullableIsNotNull(intValue: 0, intFunction: () => 0);
+  testNullAsNonNullable(nullValue: null, nullFunction: () => null, true_: true);
+  testNullIsNonNullable(nullValue: null, nullFunction: () => null);
+  testNullIsNotNonNullable(nullValue: null, nullFunction: () => null);
+}