Skip to content

Commit 4caae04

Browse files
stereotype441Commit Queue
authored andcommitted
Remove the fallback exhaustiveness algorithm.
Fixes #51518. Bug: #51518 Change-Id: Ic925f0ba41555e5077fee1b0433476e8ea28b75e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/290560 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 38f33d8 commit 4caae04

File tree

23 files changed

+204
-669
lines changed

23 files changed

+204
-669
lines changed

pkg/_fe_analyzer_shared/lib/src/exhaustiveness/exhaustive.dart

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,6 @@ import 'profile.dart' as profile;
99
import 'space.dart';
1010
import 'witness.dart';
1111

12-
/// Indicates whether the "fallback" exhaustiveness algorithm (based on flow
13-
/// analysis) should be used instead of full exhaustiveness. This is a
14-
/// temporary measure to allow for the possibility of turning on pattern support
15-
/// before the full exhaustiveness algorithm is complete.
16-
///
17-
/// TODO(paulberry): remove this flag (and the implementation of the fallback
18-
/// exhaustiveness algorithm) when it is no longer needed.
19-
bool useFallbackExhaustivenessAlgorithm = false;
20-
2112
/// Returns `true` if [caseSpaces] exhaustively covers all possible values of
2213
/// [valueSpace].
2314
bool isExhaustive(

pkg/_fe_analyzer_shared/lib/src/type_inference/type_analysis_result.dart

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,10 @@ class SwitchExpressionResult<Type extends Object, Error>
178178
/// This is `null` if no such guards where present.
179179
final Map<int, Type>? guardTypes;
180180

181-
/// Error for when the switch statement was non exhaustive.
182-
final Error? nonExhaustiveSwitchError;
183-
184181
SwitchExpressionResult(
185182
{required super.type,
186183
required this.nonBooleanGuardErrors,
187-
required this.guardTypes,
188-
required this.nonExhaustiveSwitchError});
184+
required this.guardTypes});
189185
}
190186

191187
/// Container for the result of running type analysis on an integer literal.
@@ -229,9 +225,6 @@ class SwitchStatementTypeAnalysisResult<Type extends Object, Error> {
229225
/// This is `null` if no such guards where present.
230226
final Map<int, Map<int, Type>>? guardTypes;
231227

232-
/// Error for when the switch statement was non exhaustive.
233-
final Error? nonExhaustiveSwitchError;
234-
235228
SwitchStatementTypeAnalysisResult({
236229
required this.hasDefault,
237230
required this.isExhaustive,
@@ -241,7 +234,6 @@ class SwitchStatementTypeAnalysisResult<Type extends Object, Error> {
241234
required this.switchCaseCompletesNormallyErrors,
242235
required this.nonBooleanGuardErrors,
243236
required this.guardTypes,
244-
required this.nonExhaustiveSwitchError,
245237
});
246238
}
247239

pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import '../exhaustiveness/exhaustive.dart';
65
import '../flow_analysis/flow_analysis.dart';
76
import 'type_analysis_result.dart';
87
import 'type_operations.dart';
@@ -1773,19 +1772,11 @@ mixin TypeAnalyzer<
17731772
}
17741773
lubType ??= dynamicType;
17751774
// Stack: (Expression, numCases * ExpressionCase)
1776-
Error? nonExhaustiveSwitchError;
1777-
bool isProvenExhaustive = flow.switchStatement_end(true);
1778-
if (options.errorOnSwitchExhaustiveness &&
1779-
!isProvenExhaustive &&
1780-
!isLegacySwitchExhaustive(node, expressionType)) {
1781-
nonExhaustiveSwitchError =
1782-
errors.nonExhaustiveSwitch(node: node, scrutineeType: expressionType);
1783-
}
1775+
flow.switchStatement_end(true);
17841776
return new SwitchExpressionResult(
17851777
type: lubType,
17861778
nonBooleanGuardErrors: nonBooleanGuardErrors,
1787-
guardTypes: guardTypes,
1788-
nonExhaustiveSwitchError: nonExhaustiveSwitchError);
1779+
guardTypes: guardTypes);
17891780
}
17901781

17911782
/// Analyzes a statement of the form `switch (expression) { cases }`.
@@ -1913,15 +1904,7 @@ mixin TypeAnalyzer<
19131904
isExhaustive = isLegacySwitchExhaustive(node, scrutineeType);
19141905
requiresExhaustivenessValidation = false;
19151906
}
1916-
bool isProvenExhaustive = flow.switchStatement_end(isExhaustive);
1917-
Error? nonExhaustiveSwitchError;
1918-
if (options.errorOnSwitchExhaustiveness &&
1919-
requiresExhaustivenessValidation &&
1920-
!isProvenExhaustive &&
1921-
!isLegacySwitchExhaustive(node, scrutineeType)) {
1922-
nonExhaustiveSwitchError =
1923-
errors.nonExhaustiveSwitch(node: node, scrutineeType: scrutineeType);
1924-
}
1907+
flow.switchStatement_end(isExhaustive);
19251908
return new SwitchStatementTypeAnalysisResult(
19261909
hasDefault: hasDefault,
19271910
isExhaustive: isExhaustive,
@@ -1931,7 +1914,6 @@ mixin TypeAnalyzer<
19311914
switchCaseCompletesNormallyErrors: switchCaseCompletesNormallyErrors,
19321915
nonBooleanGuardErrors: nonBooleanGuardErrors,
19331916
guardTypes: guardTypes,
1934-
nonExhaustiveSwitchError: nonExhaustiveSwitchError,
19351917
);
19361918
}
19371919

@@ -2584,15 +2566,6 @@ abstract class TypeAnalyzerErrors<
25842566
/// Called if the static type of a condition is not assignable to `bool`.
25852567
Error nonBooleanCondition({required Expression node});
25862568

2587-
/// Called if [TypeAnalyzerOptions.errorOnSwitchExhaustiveness] is `true`, and
2588-
/// a switch that is required to be exhaustive cannot be proven by flow
2589-
/// analysis to be exhaustive.
2590-
///
2591-
/// [node] is the offending switch expression or switch statement, and
2592-
/// [scrutineeType] is the static type of the switch statement's scrutinee
2593-
/// expression.
2594-
Error nonExhaustiveSwitch({required Node node, required Type scrutineeType});
2595-
25962569
/// Called if a pattern is illegally used in a variable declaration statement
25972570
/// that is marked `late`, and that pattern is not allowed in such a
25982571
/// declaration. The only kind of pattern that may be used in a late variable
@@ -2698,21 +2671,6 @@ class TypeAnalyzerOptions {
26982671

26992672
final bool patternsEnabled;
27002673

2701-
/// If `true`, the type analyzer should generate errors if it encounters a
2702-
/// switch that is required to be exhaustive, but cannot be proven to be
2703-
/// exhaustive by flow analysis.
2704-
///
2705-
/// This option is intended as a temporary workaround if we want to ship an
2706-
/// early beta of the "patterns" feature before exhaustiveness checking is
2707-
/// sufficiently ready.
2708-
///
2709-
/// TODO(paulberry): remove this option when it is no longer needed.
2710-
final bool errorOnSwitchExhaustiveness;
2711-
27122674
TypeAnalyzerOptions(
2713-
{required this.nullSafetyEnabled,
2714-
required this.patternsEnabled,
2715-
bool? errorOnSwitchExhaustiveness})
2716-
: errorOnSwitchExhaustiveness =
2717-
errorOnSwitchExhaustiveness ?? useFallbackExhaustivenessAlgorithm;
2675+
{required this.nullSafetyEnabled, required this.patternsEnabled});
27182676
}

pkg/_fe_analyzer_shared/test/mini_ast.dart

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -380,10 +380,8 @@ Statement switch_(Expression expression, List<_SwitchStatementMember> cases,
380380
expectRequiresExhaustivenessValidation,
381381
expectScrutineeType: expectScrutineeType);
382382

383-
Expression switchExpr(Expression expression, List<ExpressionCase> cases,
384-
{bool? isLegacyExhaustive}) =>
385-
new _SwitchExpression(expression, cases, isLegacyExhaustive,
386-
location: computeLocation());
383+
Expression switchExpr(Expression expression, List<ExpressionCase> cases) =>
384+
new _SwitchExpression(expression, cases, location: computeLocation());
387385

388386
_SwitchStatementMember switchStatementMember(
389387
List<SwitchHead> cases,
@@ -631,8 +629,6 @@ class Harness {
631629

632630
bool? _patternsEnabled;
633631

634-
bool errorOnSwitchExhaustiveness = false;
635-
636632
Type? _thisType;
637633

638634
late final Map<String, _PropertyElement?> _members = {
@@ -644,8 +640,7 @@ class Harness {
644640
this,
645641
TypeAnalyzerOptions(
646642
nullSafetyEnabled: !_operations.legacy,
647-
patternsEnabled: patternsEnabled,
648-
errorOnSwitchExhaustiveness: errorOnSwitchExhaustiveness));
643+
patternsEnabled: patternsEnabled));
649644

650645
/// Indicates whether initializers of implicitly typed variables should be
651646
/// accounted for by SSA analysis. (In an ideal world, they always would be,
@@ -3125,12 +3120,6 @@ class _MiniAstErrors
31253120
_recordError('nonBooleanCondition', {'node': node});
31263121
}
31273122

3128-
@override
3129-
void nonExhaustiveSwitch({required Node node, required Type scrutineeType}) {
3130-
_recordError(
3131-
'nonExhaustiveSwitch', {'node': node, 'scrutineeType': scrutineeType});
3132-
}
3133-
31343123
@override
31353124
void patternDoesNotAllowLate({required Node pattern}) {
31363125
_recordError('patternDoesNotAllowLate', {'pattern': pattern});
@@ -3872,7 +3861,8 @@ class _MiniAstTypeAnalyzer
38723861
operations.isAlwaysExhaustiveType(type);
38733862

38743863
@override
3875-
bool isLegacySwitchExhaustive(covariant _Switch node, Type expressionType) {
3864+
bool isLegacySwitchExhaustive(
3865+
covariant _SwitchStatement node, Type expressionType) {
38763866
return node.isLegacyExhaustive!;
38773867
}
38783868

@@ -4512,20 +4502,12 @@ class _Return extends Statement {
45124502
}
45134503
}
45144504

4515-
abstract class _Switch implements Node {
4516-
bool? get isLegacyExhaustive;
4517-
}
4518-
4519-
class _SwitchExpression extends Expression implements _Switch {
4505+
class _SwitchExpression extends Expression {
45204506
final Expression scrutinee;
45214507

45224508
final List<ExpressionCase> cases;
45234509

4524-
@override
4525-
final bool? isLegacyExhaustive;
4526-
4527-
_SwitchExpression(this.scrutinee, this.cases, this.isLegacyExhaustive,
4528-
{required super.location});
4510+
_SwitchExpression(this.scrutinee, this.cases, {required super.location});
45294511

45304512
@override
45314513
void preVisit(PreVisitor visitor) {
@@ -4537,30 +4519,18 @@ class _SwitchExpression extends Expression implements _Switch {
45374519

45384520
@override
45394521
String toString() {
4540-
var isLegacyExhaustive = this.isLegacyExhaustive;
4541-
var exhaustiveness = isLegacyExhaustive == null
4542-
? ''
4543-
: isLegacyExhaustive
4544-
? '<exhaustive>'
4545-
: '<non-exhaustive>';
45464522
String body;
45474523
if (cases.isEmpty) {
45484524
body = '{}';
45494525
} else {
45504526
var contents = cases.join(' ');
45514527
body = '{ $contents }';
45524528
}
4553-
return 'switch$exhaustiveness ($scrutinee) $body';
4529+
return 'switch ($scrutinee) $body';
45544530
}
45554531

45564532
@override
45574533
ExpressionTypeAnalysisResult<Type> visit(Harness h, Type context) {
4558-
bool needsLegacyExhaustive = h.errorOnSwitchExhaustiveness;
4559-
if (!needsLegacyExhaustive && isLegacyExhaustive != null) {
4560-
fail('isLegacyExhaustive should not be specified at $location');
4561-
} else if (needsLegacyExhaustive && isLegacyExhaustive == null) {
4562-
fail('isLegacyExhaustive should be specified at $location');
4563-
}
45644534
var result = h.typeAnalyzer
45654535
.analyzeSwitchExpression(this, scrutinee, cases.length, context);
45664536
h.irBuilder.apply(
@@ -4582,12 +4552,11 @@ class _SwitchHeadDefault extends SwitchHead {
45824552
_SwitchHeadDefault({required super.location}) : super._();
45834553
}
45844554

4585-
class _SwitchStatement extends Statement implements _Switch {
4555+
class _SwitchStatement extends Statement {
45864556
final Expression scrutinee;
45874557

45884558
final List<_SwitchStatementMember> cases;
45894559

4590-
@override
45914560
final bool? isLegacyExhaustive;
45924561

45934562
final bool? expectHasDefault;
@@ -4638,8 +4607,7 @@ class _SwitchStatement extends Statement implements _Switch {
46384607

46394608
@override
46404609
void visit(Harness h) {
4641-
bool needsLegacyExhaustive =
4642-
!h.patternsEnabled || h.errorOnSwitchExhaustiveness;
4610+
bool needsLegacyExhaustive = !h.patternsEnabled;
46434611
if (!needsLegacyExhaustive && isLegacyExhaustive != null) {
46444612
fail('isLegacyExhaustive should not be specified at $location');
46454613
} else if (needsLegacyExhaustive && isLegacyExhaustive == null) {

0 commit comments

Comments
 (0)