[_fe_analyzer_shared] Exclude patterns with when clauses from exhaustiveness
Change-Id: I6cc552854139d9476c9b33d93a6d7fdc55e845a3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/285903
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/_fe_analyzer_shared/test/exhaustiveness/data/when.dart b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/when.dart
new file mode 100644
index 0000000..928a5b9
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/exhaustiveness/data/when.dart
@@ -0,0 +1,55 @@
+// 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.
+
+sealed class A {
+ int get field;
+}
+
+class B extends A {
+ final int field;
+ B(this.field);
+}
+
+class C extends A {
+ final int field;
+
+ C(this.field);
+}
+
+method(A a) {
+ /*
+ fields={field:int,hashCode:int,runtimeType:Type},
+ subtypes={B,C},
+ type=A
+ */switch (a) {
+ /*space=B*/case B():
+ /*space=C*/case C():
+ }
+ /*
+ fields={field:int,hashCode:int,runtimeType:Type},
+ subtypes={B,C},
+ type=A
+ */switch (a) {
+ /*space=B(field: int)*/case B(:var field):
+ /*space=C(field: int)*/case C(:var field):
+ }
+ /*
+ error=non-exhaustive:B,
+ fields={field:int,hashCode:int,runtimeType:Type},
+ subtypes={B,C},
+ type=A
+ */switch (a) {
+ /*space=??*/case B(:var field) when field > 0:
+ /*space=C(field: int)*/case C(:var field):
+ }
+ /*
+ error=non-exhaustive:C,
+ fields={field:int,hashCode:int,runtimeType:Type},
+ subtypes={B,C},
+ type=A
+ */switch (a) {
+ /*space=B(field: int)*/case B(:var field):
+ /*space=??*/case C(:var field) when field > 0:
+ }
+}
\ No newline at end of file
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index a6c4fee..4fc9a29 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -780,7 +780,6 @@
if (guardedPattern != null) {
Space space;
if (guardedPattern.whenClause != null) {
- // TODO(johnniwinther): Test this.
space = Space(_exhaustivenessCache.getUnknownStaticType());
} else {
final pattern = guardedPattern.pattern;
diff --git a/pkg/front_end/lib/src/fasta/kernel/exhaustiveness.dart b/pkg/front_end/lib/src/fasta/kernel/exhaustiveness.dart
index f9aa7a0..3633324 100644
--- a/pkg/front_end/lib/src/fasta/kernel/exhaustiveness.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/exhaustiveness.dart
@@ -341,14 +341,19 @@
class PatternCaseInfo extends SwitchCaseInfo {
final Pattern pattern;
+
+ final bool hasGuard;
+
@override
final int fileOffset;
- PatternCaseInfo(this.pattern, {required this.fileOffset});
+ PatternCaseInfo(this.pattern,
+ {required this.hasGuard, required this.fileOffset});
@override
Space createSpace(CfeExhaustivenessCache cache,
Map<Node, Constant?> constants, StaticTypeContext context) {
+ if (hasGuard) return new Space(cache.getUnknownStaticType());
return convertPatternToSpace(cache, pattern, constants, context,
nonNull: false);
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
index e45e01e..c1ccde5 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
@@ -9856,6 +9856,7 @@
pushRewrite(case_);
_switchCasePatternInfo.add(new PatternCaseInfo(patternGuard.pattern,
+ hasGuard: patternGuard.guard != null,
fileOffset: case_.caseOffsets[subIndex]));
}
} else {
@@ -9891,6 +9892,7 @@
}
}
_switchCasePatternInfo.add(new PatternCaseInfo(patternGuard.pattern,
+ hasGuard: patternGuard.guard != null,
fileOffset: switchExpressionCase.fileOffset));
}
}
diff --git a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.strong.expect b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.strong.expect
index 5598ff4..8f7c3a5 100644
--- a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.strong.expect
+++ b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.strong.expect
@@ -1,4 +1,12 @@
library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart:5:16: Error: The type 'dynamic' is not exhaustively matched by the switch cases.
+// Try adding a default case or cases that match Object.
+// f(x) => switch(x) {
+// ^
+//
import self as self;
import "dart:core" as core;
diff --git a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.strong.transformed.expect
index 78bd2f1..0bbfc21 100644
--- a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.strong.transformed.expect
@@ -1,4 +1,12 @@
library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart:5:16: Error: The type 'dynamic' is not exhaustively matched by the switch cases.
+// Try adding a default case or cases that match Object.
+// f(x) => switch(x) {
+// ^
+//
import self as self;
import "dart:core" as core;
diff --git a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.expect b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.expect
index 5598ff4..8f7c3a5 100644
--- a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.expect
+++ b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.expect
@@ -1,4 +1,12 @@
library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart:5:16: Error: The type 'dynamic' is not exhaustively matched by the switch cases.
+// Try adding a default case or cases that match Object.
+// f(x) => switch(x) {
+// ^
+//
import self as self;
import "dart:core" as core;
diff --git a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.modular.expect
index 5598ff4..8f7c3a5 100644
--- a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.modular.expect
@@ -1,4 +1,12 @@
library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart:5:16: Error: The type 'dynamic' is not exhaustively matched by the switch cases.
+// Try adding a default case or cases that match Object.
+// f(x) => switch(x) {
+// ^
+//
import self as self;
import "dart:core" as core;
diff --git a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.transformed.expect
index 78bd2f1..0bbfc21 100644
--- a/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart.weak.transformed.expect
@@ -1,4 +1,12 @@
library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/switchExpression_onePattern_guarded.dart:5:16: Error: The type 'dynamic' is not exhaustively matched by the switch cases.
+// Try adding a default case or cases that match Object.
+// f(x) => switch(x) {
+// ^
+//
import self as self;
import "dart:core" as core;