mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
[_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:
parent
efc9ebb215
commit
032996f45c
9 changed files with 103 additions and 2 deletions
55
pkg/_fe_analyzer_shared/test/exhaustiveness/data/when.dart
Normal file
55
pkg/_fe_analyzer_shared/test/exhaustiveness/data/when.dart
Normal 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:
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue