mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 08:24:39 +00:00
Add SwitchStatementTypeAnalysisResult.requiresExhaustivenessValidation.
This boolean tells the analyzer and front end whether it is required to run the exhaustiness algorithm on the switch statement (and to report an error if the switch isn't exhaustive). Bug: https://github.com/dart-lang/sdk/issues/50585 Change-Id: I8c95e563bd59a83cf5e1b94170af5c4f8b5c6496 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/274925 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
parent
a29cd031d3
commit
9169abc8f4
|
@ -125,6 +125,14 @@ class SwitchStatementTypeAnalysisResult<Type> {
|
|||
/// Whether the last case body in the switch statement terminated.
|
||||
final bool lastCaseTerminates;
|
||||
|
||||
/// If `true`, patterns support is enabled, there is no default clause, and
|
||||
/// the static type of the scrutinee expression is an "always exhaustive"
|
||||
/// type. Therefore, flow analysis has assumed (without checking) that the
|
||||
/// switch statement is exhaustive. So at a later stage of compilation, the
|
||||
/// exhaustiveness checking algorithm should check whether this switch
|
||||
/// statement was exhaustive, and report a compile-time error if it wasn't.
|
||||
final bool requiresExhaustivenessValidation;
|
||||
|
||||
/// The static type of the scrutinee expression.
|
||||
final Type scrutineeType;
|
||||
|
||||
|
@ -132,6 +140,7 @@ class SwitchStatementTypeAnalysisResult<Type> {
|
|||
required this.hasDefault,
|
||||
required this.isExhaustive,
|
||||
required this.lastCaseTerminates,
|
||||
required this.requiresExhaustivenessValidation,
|
||||
required this.scrutineeType,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1352,18 +1352,23 @@ mixin TypeAnalyzer<
|
|||
}
|
||||
// Stack: (Expression, numExecutionPaths * StatementCase)
|
||||
bool isExhaustive;
|
||||
bool requiresExhaustivenessValidation;
|
||||
if (hasDefault) {
|
||||
isExhaustive = true;
|
||||
requiresExhaustivenessValidation = false;
|
||||
} else if (options.patternsEnabled) {
|
||||
isExhaustive = isAlwaysExhaustiveType(scrutineeType);
|
||||
requiresExhaustivenessValidation =
|
||||
isExhaustive = isAlwaysExhaustiveType(scrutineeType);
|
||||
} else {
|
||||
isExhaustive = isLegacySwitchExhaustive(node, scrutineeType);
|
||||
requiresExhaustivenessValidation = false;
|
||||
}
|
||||
flow.switchStatement_end(isExhaustive);
|
||||
return new SwitchStatementTypeAnalysisResult<Type>(
|
||||
hasDefault: hasDefault,
|
||||
isExhaustive: isExhaustive,
|
||||
lastCaseTerminates: lastCaseTerminates,
|
||||
requiresExhaustivenessValidation: requiresExhaustivenessValidation,
|
||||
scrutineeType: scrutineeType,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -327,12 +327,15 @@ Statement switch_(Expression expression, List<_SwitchStatementMember> cases,
|
|||
bool? expectHasDefault,
|
||||
bool? expectIsExhaustive,
|
||||
bool? expectLastCaseTerminates,
|
||||
bool? expectRequiresExhaustivenessValidation,
|
||||
String? expectScrutineeType}) =>
|
||||
new _SwitchStatement(expression, cases, isLegacyExhaustive,
|
||||
location: computeLocation(),
|
||||
expectHasDefault: expectHasDefault,
|
||||
expectIsExhaustive: expectIsExhaustive,
|
||||
expectLastCaseTerminates: expectLastCaseTerminates,
|
||||
expectRequiresExhaustivenessValidation:
|
||||
expectRequiresExhaustivenessValidation,
|
||||
expectScrutineeType: expectScrutineeType);
|
||||
|
||||
Expression switchExpr(Expression expression, List<ExpressionCase> cases) =>
|
||||
|
@ -4288,6 +4291,8 @@ class _SwitchStatement extends Statement {
|
|||
|
||||
final bool? expectLastCaseTerminates;
|
||||
|
||||
final bool? expectRequiresExhaustivenessValidation;
|
||||
|
||||
final String? expectScrutineeType;
|
||||
|
||||
_SwitchStatement(this.scrutinee, this.cases, this.isLegacyExhaustive,
|
||||
|
@ -4295,6 +4300,7 @@ class _SwitchStatement extends Statement {
|
|||
required this.expectHasDefault,
|
||||
required this.expectIsExhaustive,
|
||||
required this.expectLastCaseTerminates,
|
||||
required this.expectRequiresExhaustivenessValidation,
|
||||
required this.expectScrutineeType});
|
||||
|
||||
@override
|
||||
|
@ -4344,6 +4350,8 @@ class _SwitchStatement extends Statement {
|
|||
expect(analysisResult.isExhaustive, expectIsExhaustive ?? anything);
|
||||
expect(analysisResult.lastCaseTerminates,
|
||||
expectLastCaseTerminates ?? anything);
|
||||
expect(analysisResult.requiresExhaustivenessValidation,
|
||||
expectRequiresExhaustivenessValidation ?? anything);
|
||||
expect(analysisResult.scrutineeType.type, expectScrutineeType ?? anything);
|
||||
h.irBuilder.apply(
|
||||
'switch',
|
||||
|
|
|
@ -1314,6 +1314,70 @@ main() {
|
|||
], expectedErrors: {});
|
||||
});
|
||||
});
|
||||
|
||||
group('requiresExhaustivenessValidation:', () {
|
||||
test('When a `default` clause is present', () {
|
||||
h.addExhaustiveness('E', true);
|
||||
h.run([
|
||||
switch_(
|
||||
expr('E'),
|
||||
[
|
||||
default_.then([
|
||||
break_(),
|
||||
]),
|
||||
],
|
||||
expectRequiresExhaustivenessValidation: false,
|
||||
),
|
||||
]);
|
||||
});
|
||||
|
||||
test('When the scrutinee is an always-exhaustive type', () {
|
||||
h.addExhaustiveness('E', true);
|
||||
h.run([
|
||||
switch_(
|
||||
expr('E'),
|
||||
[
|
||||
expr('E').pattern.then([
|
||||
break_(),
|
||||
]),
|
||||
],
|
||||
expectRequiresExhaustivenessValidation: true,
|
||||
),
|
||||
]);
|
||||
});
|
||||
|
||||
test('When the scrutinee is not an always-exhaustive type', () {
|
||||
h.addExhaustiveness('C', false);
|
||||
h.run([
|
||||
switch_(
|
||||
expr('C'),
|
||||
[
|
||||
expr('C').pattern.then([
|
||||
break_(),
|
||||
]),
|
||||
],
|
||||
expectRequiresExhaustivenessValidation: false,
|
||||
),
|
||||
]);
|
||||
});
|
||||
|
||||
test('When pattern support is disabled', () {
|
||||
h.patternsEnabled = false;
|
||||
h.addExhaustiveness('E', true);
|
||||
h.run([
|
||||
switch_(
|
||||
expr('E'),
|
||||
[
|
||||
expr('E').pattern.then([
|
||||
break_(),
|
||||
]),
|
||||
],
|
||||
isLegacyExhaustive: true,
|
||||
expectRequiresExhaustivenessValidation: false,
|
||||
),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('Variable declaration:', () {
|
||||
|
|
Loading…
Reference in a new issue