[_fe_shared_analyzer] Use real exhaustiveness checking algorithm

This changes the analyzer and CFE to use the real exhaustiveness
checking algorithm. The fallback algorithm is kept and will be
removed once we know that the real exhaustiveness algorithm sticks.

Change-Id: Ic9df92c1ca9f7dec4cbdfa138dc6ed39ef2d4df5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/288703
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/exhaustiveness/exhaustive.dart b/pkg/_fe_analyzer_shared/lib/src/exhaustiveness/exhaustive.dart
index 0ee6043..bdf60d5 100644
--- a/pkg/_fe_analyzer_shared/lib/src/exhaustiveness/exhaustive.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/exhaustiveness/exhaustive.dart
@@ -16,7 +16,7 @@
 ///
 /// TODO(paulberry): remove this flag (and the implementation of the fallback
 /// exhaustiveness algorithm) when it is no longer needed.
-bool useFallbackExhaustivenessAlgorithm = true;
+bool useFallbackExhaustivenessAlgorithm = false;
 
 /// Returns `true` if [caseSpaces] exhaustively covers all possible values of
 /// [valueSpace].
diff --git a/pkg/_fe_analyzer_shared/lib/src/exhaustiveness/shared.dart b/pkg/_fe_analyzer_shared/lib/src/exhaustiveness/shared.dart
index a21b1bb..2647d63 100644
--- a/pkg/_fe_analyzer_shared/lib/src/exhaustiveness/shared.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/exhaustiveness/shared.dart
@@ -225,8 +225,12 @@
 
   /// Creates a new unique [StaticType].
   StaticType getUnknownStaticType() {
+    // The unknown static type should be based on the nullable `Object`, since
+    // even though it _might_ be `null`, using the nullable `Object` here would
+    // mean that it _does_ include `null`, and we need this type to only cover
+    // itself.
     return getUniqueStaticType<Object>(
-        typeOperations.nullableObjectType, new Object(), '?');
+        typeOperations.nonNullableObjectType, new Object(), '?');
   }
 
   /// Returns a [StaticType] of the given [type] with the given
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/and_pattern.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/and_pattern.dart
index fe8f05a..6d9258b26 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/and_pattern.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/and_pattern.dart
@@ -79,8 +79,8 @@
    fields={field1:B},
    type=A
   */switch (o2) {
-  A(field1: C() || D()) && A(field1: D() || E()) /*space=A(field1: D|??)*/=> 0,
-  A(field1: C() || E()) && A(field1: C() || E()) /*space=A(field1: C|E|??)*/=> 1,
+  A(field1: C() || D()) && A(field1: D() || E()) /*space=A(field1: D|?)*/=> 0,
+  A(field1: C() || E()) && A(field1: C() || E()) /*space=A(field1: C|E|?)*/=> 1,
   };
   var c = /*
    subtypes={C,D,E},
@@ -93,6 +93,6 @@
    subtypes={C,D,E},
    type=B
   */switch (o3) {
-    (C() || D() || E()) && (C() || D() || E()) /*space=C|D|E|??*/=> 0,
+    (C() || D() || E()) && (C() || D() || E()) /*space=C|D|E|?*/=> 0,
   };
 }
\ No newline at end of file
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/bool.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/bool.dart
index ee205f3..d4edf87 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/bool.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/bool.dart
@@ -89,7 +89,6 @@
 
 void nonExhaustiveSwitchWithDefault(bool b) {
   /*
-   error=non-exhaustive:false,
    subtypes={true,false},
    type=bool
   */
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/empty.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/empty.dart
new file mode 100644
index 0000000..7890576
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/empty.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2023, 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.
+
+emptyBool(bool b) {
+  return /*analyzer.
+   error=non-exhaustive:true,
+   subtypes={true,false},
+   type=bool
+  */
+  switch (b) {
+  };
+}
+
+emptyNum(num n) {
+  return /*analyzer.
+   error=non-exhaustive:double,
+   subtypes={double,int},
+   type=num
+  */
+  switch (n) {
+  };
+}
+
+emptyInt(int i) {
+  return /*analyzer.
+   error=non-exhaustive:int,
+   type=int
+  */
+  switch (i) {
+  };
+}
+
+enum E { a, b }
+
+emptyEnum(E e) {
+  return /*analyzer.
+   error=non-exhaustive:E.a,
+   subtypes={E.a,E.b},
+   type=E
+  */
+  switch (e) {
+  };
+}
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/enum.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/enum.dart
index f9199d2..e0d03b7 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/enum.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/enum.dart
@@ -145,7 +145,6 @@
 
 void nonExhaustiveSwitchWithDefault(Enum e) {
   /*
-   error=non-exhaustive:Enum.a,
    subtypes={Enum.a,Enum.b,Enum.c},
    type=Enum
   */
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/generic_sealed_class.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/generic_sealed_class.dart
index 4655567..bb91756 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/generic_sealed_class.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/generic_sealed_class.dart
@@ -195,7 +195,6 @@
 
 void nonExhaustiveSwitchWithDefault(A<dynamic> a) {
   /*
-   error=non-exhaustive:B<dynamic>,
    subtypes={B<dynamic>,C,D<dynamic, dynamic>},
    type=A<dynamic>
   */
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/num.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/num.dart
new file mode 100644
index 0000000..37d2bb6
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/num.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2023, 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.
+
+exhaustiveSwitchNum(num n) {
+  /*
+   subtypes={double,int},
+   type=num
+  */
+  switch (n) {
+    /*space=num*/
+    case num n:
+  }
+}
+
+exhaustiveSwitchIntDouble(num n) {
+  /*
+   subtypes={double,int},
+   type=num
+  */
+  switch (n) {
+    /*space=int*/
+    case int i:
+    /*space=double*/
+    case double d:
+  }
+}
+
+exhaustiveSwitchNullable(num? n) {
+  /*
+   expandedSubtypes={double,int,Null},
+   subtypes={num,Null},
+   type=num?
+  */
+  switch (n) {
+    /*space=int*/
+    case int i:
+    /*space=double*/
+    case double d:
+    /*space=Null*/
+    case null:
+  }
+}
+
+nonExhaustiveSwitch(num n1, num n2, num? n3) {
+  /*
+   error=non-exhaustive:double,
+   subtypes={double,int},
+   type=num
+  */
+  switch (n1) {
+    /*space=int*/
+    case int i:
+  }
+  /*
+   error=non-exhaustive:int,
+   subtypes={double,int},
+   type=num
+  */
+  switch (n2) {
+    /*space=double*/
+    case double d:
+  }
+  /*
+   error=non-exhaustive:Null,
+   expandedSubtypes={double,int,Null},
+   subtypes={num,Null},
+   type=num?
+  */
+  switch (n3) {
+    /*space=int*/
+    case int i:
+    /*space=double*/
+    case double d:
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/object_pattern.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/object_pattern.dart
index bd98552..afcb0f3 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/object_pattern.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/object_pattern.dart
@@ -115,7 +115,6 @@
 
 void nonExhaustiveSwitchWithDefault(A r) {
   /*
-   error=non-exhaustive:B(a: Enum.a, b: true),
    fields={a:Enum,b:bool},
    subtypes={B},
    type=A
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record.dart
index 482f834..fe53793 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record.dart
@@ -79,7 +79,6 @@
 
 void nonExhaustiveSwitchWithDefault((Enum, bool) r) {
   /*
-   error=non-exhaustive:($1: Enum.a, $2: true),
    fields={$1:Enum,$2:bool},
    type=(Enum, bool)
   */
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_literal.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_literal.dart
index 341e55e..ead179f 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_literal.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_literal.dart
@@ -75,7 +75,6 @@
 
 void nonExhaustiveSwitchWithDefault((Enum, bool) r) {
   /*
-   error=non-exhaustive:($1: Enum.a, $2: true),
    fields={$1:Enum,$2:bool},
    type=(Enum, bool)
   */
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_literal_named.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_literal_named.dart
index eba97de..dfec68e 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_literal_named.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_literal_named.dart
@@ -74,7 +74,6 @@
 
 void nonExhaustiveSwitchWithDefault(({Enum a, bool b}) r) {
   /*
-   error=non-exhaustive:(a: Enum.a, b: true),
    fields={a:Enum,b:bool},
    type=({Enum a, bool b})
   */switch (r) {
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_sealed.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_sealed.dart
index b35aa01..e5c79b3 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_sealed.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/record_sealed.dart
@@ -12,17 +12,13 @@
 }
 
 method(Class c) {
-  /*analyzer.
-   error=non-exhaustive:Class(field: ($1: C, $2: C)),
+  /*
    fields={field:(A, A)},
    type=Class
-  */
-  switch (c) {
-    /*analyzer.space=Class(field: ($1: A, $2: B))*/
-    case Class(field: (A a, B b)):
+  */switch (c) {
+    /*space=Class(field: ($1: A, $2: B))*/case Class(field: (A a, B b)):
       print('1');
-    /*analyzer.space=Class(field: ($1: B, $2: A))*/
-    case Class(field: (B b, A a)):
+    /*space=Class(field: ($1: B, $2: A))*/case Class(field: (B b, A a)):
       print('2');
     default:
   }
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/relational.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/relational.dart
index 90f64b9..18badba 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/relational.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/relational.dart
@@ -7,7 +7,7 @@
    subtypes={Object,Null},
    type=Object?
   */switch (o1) {
-    == 0 /*space=??*/=> 0,
+    == 0 /*space=?*/=> 0,
     _ /*space=()*/=> 1
   };
 
@@ -16,7 +16,7 @@
    subtypes={Object,Null},
    type=Object?
   */switch (o2) {
-    == 0 /*space=??*/=> 0,
+    == 0 /*space=?*/=> 0,
   };
 }
 
@@ -25,7 +25,7 @@
    subtypes={Object,Null},
    type=Object?
   */switch (o1) {
-    >= 0 /*space=??*/=> 0,
+    >= 0 /*space=?*/=> 0,
     _ /*space=()*/=> 1
   };
 
@@ -34,6 +34,6 @@
    subtypes={Object,Null},
    type=Object?
   */switch (o2) {
-    >= 0 /*space=??*/=> 0,
+    >= 0 /*space=?*/=> 0,
   };
 }
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/sealed_class.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/sealed_class.dart
index 38fa2c2..9cae2b2 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/sealed_class.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/sealed_class.dart
@@ -103,7 +103,6 @@
 
 void nonExhaustiveSwitchWithDefault(A a) {
   /*
-   error=non-exhaustive:C,
    subtypes={B,C,D},
    type=A
   */
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/unknown.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/unknown.dart
new file mode 100644
index 0000000..035e20d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/unknown.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2023, 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.
+
+final unknownShouldNotIncludeNull = /*type=Null*/switch (null) {
+  int(:var isEven) when isEven /*space=?*/=> 1,
+  _ /*space=Null*/=> 0,
+};
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/variable_pattern.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/variable_pattern.dart
index fd4270b..edfb915 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/variable_pattern.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/variable_pattern.dart
@@ -94,7 +94,6 @@
 
 void nonExhaustiveSwitchWithDefault((Enum, bool) r) {
   /*
-   error=non-exhaustive:($1: Enum.b, $2: true),
    fields={$1:Enum,$2:bool},
    type=(Enum, bool)
   */
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/when.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/when.dart
index 298c455..c4232af 100644
--- a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/when.dart
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/when.dart
@@ -39,7 +39,7 @@
    subtypes={B,C},
    type=A
   */switch (a) {
-    /*space=??*/case B(:var field) when field > 0:
+    /*space=?*/case B(:var field) when field > 0:
     /*space=C(field: int)*/case C(:var field):
   }
   /*
@@ -49,6 +49,6 @@
    type=A
   */switch (a) {
     /*space=B(field: int)*/case B(:var field):
-    /*space=??*/case C(:var field) when field > 0:
+    /*space=?*/case C(:var field) when field > 0:
   }
 }
\ No newline at end of file
diff --git a/pkg/analysis_server/test/src/utilities/selection_test.dart b/pkg/analysis_server/test/src/utilities/selection_test.dart
index 6d8be68..116cbf7 100644
--- a/pkg/analysis_server/test/src/utilities/selection_test.dart
+++ b/pkg/analysis_server/test/src/utilities/selection_test.dart
@@ -805,6 +805,7 @@
     [!2 => '2',
     3 => '3'!],
     4 => '4',
+    _ => '5',
   };
 }
 '''));
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 48071d1..a72c008 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -402,6 +402,7 @@
         caseNodes: node.cases,
         mapPatternKeyValues: mapPatternKeyValues,
         constantPatternValues: constantPatternValues,
+        mustBeExhaustive: true,
       );
     });
   }
@@ -418,6 +419,8 @@
           caseNodes: node.members,
           mapPatternKeyValues: mapPatternKeyValues,
           constantPatternValues: constantPatternValues,
+          mustBeExhaustive:
+              _typeSystem.isAlwaysExhaustive(node.expression.typeOrThrow),
         );
       } else if (_currentLibrary.isNonNullableByDefault) {
         _validateSwitchStatement_nullSafety(node);
@@ -764,6 +767,7 @@
     required List<AstNode> caseNodes,
     required Map<Expression, DartObjectImpl> mapPatternKeyValues,
     required Map<ConstantPattern, DartObjectImpl> constantPatternValues,
+    required bool mustBeExhaustive,
   }) {
     final scrutineeType = scrutinee.typeOrThrow;
     final scrutineeTypeEx = _exhaustivenessCache.getStaticType(scrutineeType);
@@ -805,6 +809,7 @@
     // Compute and report errors.
     final errors =
         reportErrors(_exhaustivenessCache, scrutineeTypeEx, caseSpaces);
+    final reportNonExhaustive = mustBeExhaustive && !hasDefault;
     if (!useFallbackExhaustivenessAlgorithm) {
       for (final error in errors) {
         if (error is UnreachableCaseError) {
@@ -821,9 +826,7 @@
             HintCode.UNREACHABLE_SWITCH_CASE,
             errorToken,
           );
-        } else if (error is NonExhaustiveError &&
-            _typeSystem.isAlwaysExhaustive(scrutineeType) &&
-            !hasDefault) {
+        } else if (error is NonExhaustiveError && reportNonExhaustive) {
           _errorReporter.reportErrorForToken(
             CompileTimeErrorCode.NON_EXHAUSTIVE_SWITCH,
             switchKeyword,
@@ -845,7 +848,7 @@
         if (error is UnreachableCaseError) {
           exhaustivenessDataForTesting.errors[caseNodesWithSpace[error.index]] =
               error;
-        } else {
+        } else if (reportNonExhaustive) {
           exhaustivenessDataForTesting.errors[node] = error;
         }
       }
diff --git a/pkg/analyzer/test/src/dart/resolution/declared_variable_pattern_test.dart b/pkg/analyzer/test/src/dart/resolution/declared_variable_pattern_test.dart
index a1d0b32..7f09594 100644
--- a/pkg/analyzer/test/src/dart/resolution/declared_variable_pattern_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/declared_variable_pattern_test.dart
@@ -2,7 +2,7 @@
 // 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.
 
-import 'package:analyzer/src/dart/error/hint_codes.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'context_collection_resolution.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_wildcard_pattern_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_wildcard_pattern_test.dart
index 4a0b7e8..fedb50b 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_wildcard_pattern_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_wildcard_pattern_test.dart
@@ -158,6 +158,7 @@
 void f(Object? x) {
   (switch (x) {
     0 && _ => 0,
+    _ => 1,
   });
 }
 ''', [
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index cc7a1e0..8e7561d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -1089,16 +1089,22 @@
     //  function.
     replacementStatement..parent = node.parent;
 
-    if (computeIsAlwaysExhaustiveType(
-        node.expressionType!, typeEnvironment.coreTypes)) {
-      List<PatternGuard> patternGuards = [];
-      for (PatternSwitchCase switchCase in node.cases) {
-        patternGuards.addAll(switchCase.patternGuards);
+    List<PatternGuard> patternGuards = [];
+    // TODO(johnniwinther): Use `PatternSwitchStatement.hasDefault` instead.
+    bool hasDefault = false;
+    for (PatternSwitchCase switchCase in node.cases) {
+      patternGuards.addAll(switchCase.patternGuards);
+      if (switchCase.isDefault) {
+        hasDefault = true;
       }
-      _checkExhaustiveness(
-          node, replacementStatement, scrutineeType, patternGuards,
-          hasDefault: node.hasDefault, fileOffset: node.expression.fileOffset);
     }
+    _checkExhaustiveness(
+        node, replacementStatement, scrutineeType, patternGuards,
+        hasDefault: hasDefault,
+        mustBeExhaustive: computeIsAlwaysExhaustiveType(
+            scrutineeType, typeEnvironment.coreTypes),
+        fileOffset: node.expression.fileOffset);
+
     // TODO(johnniwinther): Remove this work-around for the `libraryOf`
     //  function.
     replacementStatement..parent = node.parent;
@@ -1109,7 +1115,9 @@
 
   void _checkExhaustiveness(TreeNode node, TreeNode replacement,
       DartType expressionType, List<PatternGuard> patternGuards,
-      {required int fileOffset, required bool hasDefault}) {
+      {required int fileOffset,
+      required bool hasDefault,
+      required bool mustBeExhaustive}) {
     StaticType type = exhaustivenessCache.getStaticType(expressionType);
     List<Space> cases = [];
     PatternConverter patternConverter =
@@ -1120,16 +1128,31 @@
     }
     List<ExhaustivenessError> errors =
         reportErrors(exhaustivenessCache, type, cases);
+    List<ExhaustivenessError>? reportedErrors;
+    if (_exhaustivenessDataForTesting != null) {
+      reportedErrors = [];
+    }
     if (!useFallbackExhaustivenessAlgorithm) {
+      Library library = _staticTypeContext!.enclosingLibrary;
       for (ExhaustivenessError error in errors) {
         if (error is UnreachableCaseError) {
-          constantEvaluator.errorReporter.report(
+          if (library.importUri.isScheme('dart') &&
+              library.importUri.path == 'html') {
+            // TODO(51754): Remove this.
+            continue;
+          }
+          reportedErrors?.add(error);
+          // TODO(johnniwinther): Re-enable this, pending resolution on
+          // https://github.com/dart-lang/language/issues/2924
+          /*constantEvaluator.errorReporter.report(
               constantEvaluator.createLocatedMessageWithOffset(
                   node,
                   patternGuards[error.index].fileOffset,
-                  messageUnreachableSwitchCase));
-        } else if (error is NonExhaustiveError && !hasDefault) {
-          Library library = _staticTypeContext!.enclosingLibrary;
+                  messageUnreachableSwitchCase));*/
+        } else if (error is NonExhaustiveError &&
+            !hasDefault &&
+            mustBeExhaustive) {
+          reportedErrors?.add(error);
           constantEvaluator.errorReporter.report(
               constantEvaluator.createLocatedMessageWithOffset(
                   node,
@@ -1143,7 +1166,7 @@
       _exhaustivenessDataForTesting!.objectFieldLookup ??= exhaustivenessCache;
       _exhaustivenessDataForTesting!.switchResults[replacement] =
           new ExhaustivenessResult(type, cases,
-              patternGuards.map((c) => c.fileOffset).toList(), errors);
+              patternGuards.map((c) => c.fileOffset).toList(), reportedErrors!);
     }
   }
 
@@ -1467,7 +1490,9 @@
       patternGuards.add(switchCase.patternGuard);
     }
     _checkExhaustiveness(node, replacement, scrutineeType, patternGuards,
-        hasDefault: false, fileOffset: node.expression.fileOffset);
+        hasDefault: false,
+        mustBeExhaustive: true,
+        fileOffset: node.expression.fileOffset);
 
     // TODO(johnniwinther): Remove this work-around for the `libraryOf`
     //  function.
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 3e2bc7f..247be1e 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -966,6 +966,8 @@
 Unspecified/example: Fail
 UnsupportedDartExt/analyzerCode: Fail
 UnsupportedDartExt/part_wrapped_script: Fail # Example uses import declaration.
+UnreachableSwitchCase/part_wrapped_script: Fail # https://github.com/dart-lang/language/issues/2924
+UnreachableSwitchCase/script: Fail # https://github.com/dart-lang/language/issues/2924
 UnterminatedString/part_wrapped_script2: Fail
 UnterminatedString/part_wrapped_script4: Fail
 UnterminatedString/part_wrapped_script5: Fail
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.strong.expect b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.strong.expect
index d0301f5..f7f2694 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.strong.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.strong.expect
@@ -28,10 +28,6 @@
 //   switch (b) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart:119:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.strong.transformed.expect
index 2bfb00b..b5f51d4 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.strong.transformed.expect
@@ -28,10 +28,6 @@
 //   switch (b) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart:119:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.expect b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.expect
index d0301f5..f7f2694 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.expect
@@ -28,10 +28,6 @@
 //   switch (b) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart:119:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.modular.expect
index d0301f5..f7f2694 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.modular.expect
@@ -28,10 +28,6 @@
 //   switch (b) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart:119:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.transformed.expect
index 2bfb00b..b5f51d4 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart.weak.transformed.expect
@@ -28,10 +28,6 @@
 //   switch (b) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/bool_switch.dart:119:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.strong.expect b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.strong.expect
index 2957276..a3a18ff 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.strong.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.strong.expect
@@ -38,24 +38,12 @@
 //   switch (e) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:126:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:143:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
 // pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:136:11: Error: The type 'Enum' is not exhaustively matched by the switch cases.
 //  - 'Enum' is from 'pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart'.
 // Try adding a default case or cases that match Enum.c.
 //   switch (e) /* Non-exhaustive */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:181:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.strong.transformed.expect
index cbc90f4..e35a84e 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.strong.transformed.expect
@@ -38,24 +38,12 @@
 //   switch (e) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:126:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:143:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
 // pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:136:11: Error: The type 'Enum' is not exhaustively matched by the switch cases.
 //  - 'Enum' is from 'pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart'.
 // Try adding a default case or cases that match Enum.c.
 //   switch (e) /* Non-exhaustive */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:181:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.expect b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.expect
index e865b4e..13048f0 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.expect
@@ -38,24 +38,12 @@
 //   switch (e) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:126:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:143:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
 // pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:136:11: Error: The type 'Enum' is not exhaustively matched by the switch cases.
 //  - 'Enum' is from 'pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart'.
 // Try adding a default case or cases that match Enum.c.
 //   switch (e) /* Non-exhaustive */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:181:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.modular.expect
index e865b4e..13048f0 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.modular.expect
@@ -38,24 +38,12 @@
 //   switch (e) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:126:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:143:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
 // pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:136:11: Error: The type 'Enum' is not exhaustively matched by the switch cases.
 //  - 'Enum' is from 'pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart'.
 // Try adding a default case or cases that match Enum.c.
 //   switch (e) /* Non-exhaustive */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:181:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.transformed.expect
index edac84b..7863e3a 100644
--- a/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart.weak.transformed.expect
@@ -38,24 +38,12 @@
 //   switch (e) /* Error */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:126:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:143:5: Warning: This case is covered by the previous cases.
-//     case Enum.a: // Unreachable
-//     ^
-//
 // pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:136:11: Error: The type 'Enum' is not exhaustively matched by the switch cases.
 //  - 'Enum' is from 'pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart'.
 // Try adding a default case or cases that match Enum.c.
 //   switch (e) /* Non-exhaustive */ {
 //           ^
 //
-// pkg/front_end/testcases/patterns/exhaustiveness/enum_switch.dart:181:5: Warning: This case is covered by the previous cases.
-//     case null: // Unreachable
-//     ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/kernel/lib/src/ast/patterns.dart b/pkg/kernel/lib/src/ast/patterns.dart
index 06b7751..6a5ccb0 100644
--- a/pkg/kernel/lib/src/ast/patterns.dart
+++ b/pkg/kernel/lib/src/ast/patterns.dart
@@ -1824,7 +1824,8 @@
   /// Whether the switch has a `default` case.
   @override
   bool get hasDefault {
-    assert(cases.every((c) => c == cases.last || !c.isDefault));
+    // TODO(johnniwinther): Establish this, even for erroneous cases.
+    //assert(cases.every((c) => c == cases.last || !c.isDefault));
     return cases.isNotEmpty && cases.last.isDefault;
   }
 
diff --git a/tests/language/patterns/exhaustiveness/fallback_error_test.dart b/tests/language/patterns/exhaustiveness/fallback_error_test.dart
index 382cc34..b4fae05 100644
--- a/tests/language/patterns/exhaustiveness/fallback_error_test.dart
+++ b/tests/language/patterns/exhaustiveness/fallback_error_test.dart
@@ -10,6 +10,9 @@
 // considered exhaustive if either (a) it is recognized as exhaustive by flow
 // analysis, or (b) it is recognized as exhaustive by the old (pre-patterns)
 // exhaustiveness algorithm for enums.
+//
+// With the enabling of the real exhaustiveness algorithm, these switches should
+// in most cases no longer cause errors.
 
 // SharedOptions=--enable-experiment=patterns --enable-experiment=records --enable-experiment=sealed-class
 
@@ -28,11 +31,9 @@
 void typedWildcard(A a) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand that
   // a sealed class factors into its subclasses.
+  //
+  // The real exhaustiveness handles this.
   switch (a) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'A' is not exhaustively matched by the switch cases.
     case B _:
       break;
     case C _:
@@ -41,10 +42,6 @@
       break;
   }
   ignore(switch (a) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'A' is not exhaustively matched by the switch cases.
       B _ => 0,
       C _ => 1,
       D _ => 2
@@ -54,11 +51,9 @@
 void typedVariable(A a) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand that
   // a sealed class factors into its subclasses.
+  //
+  // The real exhaustiveness handles this.
   switch (a) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'A' is not exhaustively matched by the switch cases.
     case B x:
       break;
     case C x:
@@ -67,10 +62,6 @@
       break;
   }
   ignore(switch (a) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'A' is not exhaustively matched by the switch cases.
       B x => 0,
       C x => 1,
       D x => 2
@@ -80,11 +71,9 @@
 void typedObjectPattern(A a) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand that
   // a sealed class factors into its subclasses.
+  //
+  // The real exhaustiveness handles this.
   switch (a) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'A' is not exhaustively matched by the switch cases.
     case B():
       break;
     case C():
@@ -93,10 +82,6 @@
       break;
   }
   ignore(switch (a) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'A' is not exhaustively matched by the switch cases.
       B() => 0,
       C() => 1,
       D() => 2
@@ -106,19 +91,13 @@
 void logicalOrPattern(E e) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand that
   // an enum value is exhausted by enum constants separated by `||`.
+  //
+  // The real exhaustiveness handles this.
   switch (e) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'E' is not exhaustively matched by the switch cases.
     case E.e1 || E.e2:
       break;
   }
   ignore(switch (e) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'E' is not exhaustively matched by the switch cases.
       E.e1 || E.e2 => 0
   });
 }
@@ -126,39 +105,25 @@
 void logicalAndPattern(E e) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand enum
   // constants appearing on either side of `&&`.
+  //
+  // The real exhaustiveness handles this.
   switch (e) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'E' is not exhaustively matched by the switch cases.
     case E.e1 && E():
       break;
     case E.e2 && E():
       break;
   }
   switch (e) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'E' is not exhaustively matched by the switch cases.
     case E() && E.e1:
       break;
     case E() && E.e2:
       break;
   }
   ignore(switch (e) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'E' is not exhaustively matched by the switch cases.
       E.e1 && E() => 0,
       E.e2 && E() => 1
   });
   ignore(switch (e) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'E' is not exhaustively matched by the switch cases.
       E() && E.e1 => 0,
       E() && E.e2 => 1
   });
@@ -167,21 +132,15 @@
 void castPattern(E? e) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand enum
   // constants appearing inside a cast pattern.
+  //
+  // The real exhaustiveness handles this.
   switch (e) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'E?' is not exhaustively matched by the switch cases.
     case E.e1 as E:
       break;
     case E.e2:
       break;
   }
   ignore(switch (e) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'E' is not exhaustively matched by the switch cases.
       E.e1 as E => 0,
       E.e2 => 1
   });
@@ -190,11 +149,9 @@
 void nullCheckPattern(E? e) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand enum
   // constants appearing inside a null-check pattern.
+  //
+  // The real exhaustiveness handles this.
   switch (e) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'E?' is not exhaustively matched by the switch cases.
     case E.e1?:
       break;
     case E.e2:
@@ -203,10 +160,6 @@
       break;
   }
   ignore(switch (e) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'E?' is not exhaustively matched by the switch cases.
       E.e1? => 0,
       E.e2 => 1,
       null => 2
@@ -216,21 +169,15 @@
 void nullAssertPattern(E? e) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand enum
   // constants appearing inside a null-assert pattern.
+  //
+  // The real exhaustiveness handles this.
   switch (e) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'E?' is not exhaustively matched by the switch cases.
     case E.e1!:
       break;
     case E.e2:
       break;
   }
   ignore(switch (e) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'E' is not exhaustively matched by the switch cases.
       E.e1! => 0,
       //  ^
       // [analyzer] STATIC_WARNING.UNNECESSARY_NULL_ASSERT_PATTERN
@@ -242,11 +189,9 @@
 void recordPattern((E, E) r) {
   // Neither flow analysis nor the old exhaustiveness algorithm split record
   // patterns up into cases.
+  //
+  // The real exhaustiveness handles this.
   switch (r) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type '(E, E)' is not exhaustively matched by the switch cases.
     case (E.e1, E.e1):
       break;
     case (E.e1, E.e2):
@@ -256,13 +201,7 @@
     case (E.e2, E.e2):
       break;
   }
-  ignore(switch (e) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
-  // [cfe] The type 'invalid-type' is not exhaustively matched by the switch cases.
-  // [cfe] Undefined name 'e'.
+  ignore(switch (r) {
       (E.e1, E.e1) => 0,
       (E.e1, E.e2) => 1,
       (E.e2, E.e1) => 2,
@@ -273,11 +212,9 @@
 void listPattern(List<int> l) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand that
   // `[...]` matches all lists.
+  //
+  // The real exhaustiveness handles this.
   ignore(switch (l) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'List<int>' is not exhaustively matched by the switch cases.
       [...] => 0
   });
 }
@@ -285,11 +222,9 @@
 void mapPattern(Map<String, int> m) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand that
   // `{...}` matches all maps.
+  //
+  // The real exhaustiveness handles this.
   ignore(switch (m) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'Map<String, int>' is not exhaustively matched by the switch cases.
       {...} => 0
   });
 }
@@ -297,21 +232,15 @@
 void exhaustiveBoolean(bool b) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand that
   // `bool` is exhausted by `true` and `false`.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
-//^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-//        ^
-// [cfe] The type 'bool' is not exhaustively matched by the switch cases.
     case true:
       break;
     case false:
       break;
   }
   ignore(switch (b) {
-  //     ^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
-  //             ^
-  // [cfe] The type 'bool' is not exhaustively matched by the switch cases.
       true => 0,
       false => 1
   });
@@ -320,6 +249,9 @@
 void relationalPattern(E e) {
   // Neither flow analysis nor the old exhaustiveness algorithm understand that
   // `== enumValue` matches an enum value.
+  //
+  // TODO(johnniwinther): Should the real exhaustiveness handle this? The
+  // call is on the expression which we do not control.
   switch (e) {
 //^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
@@ -343,6 +275,8 @@
 void withGuard(E e) {
   // The old exhaustiveness algorithm doesn't understand guards, but for
   // soundness it will ignore any cases that are guarded.
+  //
+  // The real exhaustiveness handles this.
   switch (e) {
 //^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.NON_EXHAUSTIVE_SWITCH
diff --git a/tests/language/patterns/exhaustiveness/fallback_test.dart b/tests/language/patterns/exhaustiveness/fallback_test.dart
index 24b08c8..6a0b76a 100644
--- a/tests/language/patterns/exhaustiveness/fallback_test.dart
+++ b/tests/language/patterns/exhaustiveness/fallback_test.dart
@@ -10,6 +10,9 @@
 // considered exhaustive if either (a) it is recognized as exhaustive by flow
 // analysis, or (b) it is recognized as exhaustive by the old (pre-patterns)
 // exhaustiveness algorithm for enums.
+//
+// With the enabling of the real exhaustiveness algorithm, these switches should
+// still not cause errors.
 
 // SharedOptions=--enable-experiment=patterns --enable-experiment=records
 
@@ -25,6 +28,8 @@
 void hasDefault(bool b) {
   // Flow analysis recognizes that the presence of a `default` clause makes a
   // switch statement exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case true:
       break;
@@ -36,6 +41,8 @@
 void untypedWildcard(bool b) {
   // Flow analysis recognizes that the presence of an untyped wildcard pattern
   // (`_`) makes a switch exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case true:
       break;
@@ -51,6 +58,8 @@
 void untypedVariable(bool b) {
   // Flow analysis recognizes that the presence of an untyped variable pattern
   // makes a switch exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case true:
       break;
@@ -67,6 +76,8 @@
   // Flow analysis recognizes that the presence of a typed wildcard pattern
   // (where the type is a supertype of the scrutinee type) makes a switch
   // exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case true:
       break;
@@ -93,6 +104,8 @@
   // Flow analysis recognizes that the presence of a typed variable pattern
   // (where the type is a supertype of the scrutinee type) makes a switch
   // exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case true:
       break;
@@ -119,6 +132,8 @@
   // Flow analysis recognizes that the presence of an object pattern with no
   // fields (where the type is a supertype of the scrutinee type) makes a switch
   // exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case true:
       break;
@@ -145,6 +160,8 @@
   // Flow analysis recognizes that the presence of a logical-or pattern (where
   // one of the arms of the logical-or fully covers the scrutinee type) makes a
   // switch exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case true || bool():
       break;
@@ -165,6 +182,8 @@
   // Flow analysis recognizes that the presence of a logical-and pattern (where
   // both of the arms of the logical-and fully cover the scrutinee type) makes a
   // switch exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case bool() && Object():
       break;
@@ -177,6 +196,8 @@
 void castPattern(bool? b) {
   // Flow analysis recognizes that the presence of a cast pattern (where the
   // inner pattern fully covers the cast type) makes a switch exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case bool() as bool:
       break;
@@ -190,6 +211,8 @@
   // Flow analysis recognizes that the presence of a null assert pattern (where
   // the inner pattern fully covers the promoted type) makes a switch
   // exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (b1) {
     case bool()!:
       break;
@@ -202,6 +225,8 @@
 void nullPattern(Null n) {
   // Flow analysis recognizes that the constant `null` fully covers the type
   // `Null`.
+  //
+  // The real exhaustiveness handles this.
   switch (n) {
     case null:
       break;
@@ -214,6 +239,8 @@
 void parenthesizedPattern(bool b, E e) {
   // Flow analysis recognizes that a parenthesized pattern is equivalent to its
   // inner pattern.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case (bool()):
       break;
@@ -243,6 +270,8 @@
 void recordPattern((bool, E) r) {
   // Flow analysis recognizes that a record pattern (where the subpatterns fully
   // cover the respective field types) make a switch exhaustive.
+  //
+  // The real exhaustiveness handles this.
   switch (r) {
     case (bool(), E()):
       break;
@@ -254,6 +283,8 @@
 
 void factorNullable(bool? b) {
   // Flow analysis recognizes that the type `T?` factors into `T` and `Null`.
+  //
+  // The real exhaustiveness handles this.
   switch (b) {
     case null:
       break;
@@ -269,6 +300,8 @@
 void factorFutureOr(FutureOr<bool> x) {
   // Flow analysis recognizes that a FutureOr<T> type factors into `T` and
   // `Future<T>`.
+  //
+  // The real exhaustiveness handles this.
   switch (x) {
     case Future<bool>():
       break;
@@ -284,6 +317,8 @@
 void exhaustedEnum(E e) {
   // The old exhaustiveness algorithm recognizes that all enum values exhaust an
   // enum type.
+  //
+  // The real exhaustiveness handles this.
   switch (e) {
     case E.e1:
       break;
@@ -299,6 +334,8 @@
 void exhaustedNullableEnum(E? e) {
   // The old exhaustiveness algorithm recognizes that all enum values, plus
   // `null`, exhaust a nullable enum type.
+  //
+  // The real exhaustiveness handles this.
   switch (e) {
     case E.e1:
       break;