[_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>
This commit is contained in:
Johnni Winther 2023-02-28 16:55:29 +00:00 committed by Commit Queue
parent efc9ebb215
commit 032996f45c
9 changed files with 103 additions and 2 deletions

View file

@ -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:
}
}

View file

@ -780,7 +780,6 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
if (guardedPattern != null) {
Space space;
if (guardedPattern.whenClause != null) {
// TODO(johnniwinther): Test this.
space = Space(_exhaustivenessCache.getUnknownStaticType());
} else {
final pattern = guardedPattern.pattern;

View file

@ -341,14 +341,19 @@ class ExpressionCaseInfo extends SwitchCaseInfo {
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);
}

View file

@ -9856,6 +9856,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
pushRewrite(case_);
_switchCasePatternInfo.add(new PatternCaseInfo(patternGuard.pattern,
hasGuard: patternGuard.guard != null,
fileOffset: case_.caseOffsets[subIndex]));
}
} else {
@ -9891,6 +9892,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
}
}
_switchCasePatternInfo.add(new PatternCaseInfo(patternGuard.pattern,
hasGuard: patternGuard.guard != null,
fileOffset: switchExpressionCase.fileOffset));
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;