@@ -169,7 +169,6 @@ namespace {
169
169
}
170
170
}
171
171
}
172
-
173
172
174
173
public:
175
174
explicit Space (Type T, Identifier NameForPrinting)
@@ -202,29 +201,6 @@ namespace {
202
201
return computeSize (TC, cache);
203
202
}
204
203
205
- // Walk one level deep into the space to return whether it is
206
- // composed entirely of irrefutable patterns - these are quick to check
207
- // regardless of the size of the total type space.
208
- bool isAllIrrefutable () const {
209
- switch (getKind ()) {
210
- case SpaceKind::Empty:
211
- case SpaceKind::Type:
212
- return true ;
213
- case SpaceKind::BooleanConstant:
214
- return false ;
215
- case SpaceKind::Constructor:
216
- return llvm::all_of (getSpaces (), [](const Space &sp) {
217
- return sp.getKind () == SpaceKind::Type
218
- || sp.getKind () == SpaceKind::Empty;
219
- });
220
- case SpaceKind::Disjunct: {
221
- return llvm::all_of (getSpaces (), [](const Space &sp) {
222
- return sp.isAllIrrefutable ();
223
- });
224
- }
225
- }
226
- }
227
-
228
204
static size_t getMaximumSize () {
229
205
return MAX_SPACE_SIZE;
230
206
}
@@ -1035,16 +1011,14 @@ namespace {
1035
1011
if (subjectType && subjectType->isStructurallyUninhabited ()) {
1036
1012
return ;
1037
1013
}
1038
-
1039
- // Reject switch statements with empty blocks.
1040
- if (limitedChecking && Switch->getCases ().empty ()) {
1041
- SpaceEngine::diagnoseMissingCases (TC, Switch,
1042
- RequiresDefault::EmptySwitchBody,
1043
- SpaceEngine::Space ());
1044
- }
1045
-
1046
- // If the switch body fails to typecheck, end analysis here.
1014
+
1047
1015
if (limitedChecking) {
1016
+ // Reject switch statements with empty blocks.
1017
+ if (Switch->getCases ().empty ()) {
1018
+ SpaceEngine::diagnoseMissingCases (TC, Switch,
1019
+ /* justNeedsDefault*/ true ,
1020
+ SpaceEngine::Space ());
1021
+ }
1048
1022
return ;
1049
1023
}
1050
1024
@@ -1089,18 +1063,23 @@ namespace {
1089
1063
1090
1064
Space totalSpace (subjectType, Identifier ());
1091
1065
Space coveredSpace (spaces);
1092
-
1093
1066
size_t totalSpaceSize = totalSpace.getSize (TC);
1094
- if (totalSpaceSize > Space::getMaximumSize () && !coveredSpace.isAllIrrefutable ()) {
1095
- // Because the space is large, fall back to requiring 'default'.
1096
- //
1097
- // FIXME: Explore ways of reducing runtime of this analysis or doing
1098
- // partial analysis to recover this case.
1099
- diagnoseMissingCases (TC, Switch,
1100
- RequiresDefault::SpaceTooLarge, Space ());
1067
+ if (totalSpaceSize > Space::getMaximumSize ()) {
1068
+ // Because the space is large, we have to extend the size
1069
+ // heuristic to compensate for actually exhaustively pattern matching
1070
+ // over enormous spaces. In this case, if the covered space covers
1071
+ // as much as the total space, and there were no duplicates, then we
1072
+ // can assume the user did the right thing and that they don't need
1073
+ // a 'default' to be inserted.
1074
+ if (!sawRedundantPattern
1075
+ && coveredSpace.getSize (TC) >= totalSpaceSize) {
1076
+ return ;
1077
+ }
1078
+
1079
+ diagnoseMissingCases (TC, Switch, /* justNeedsDefault*/ true , Space ());
1101
1080
return ;
1102
1081
}
1103
-
1082
+
1104
1083
auto uncovered = totalSpace.minus (coveredSpace, TC).simplify (TC);
1105
1084
if (uncovered.isEmpty ()) {
1106
1085
return ;
@@ -1113,12 +1092,11 @@ namespace {
1113
1092
if (Space::canDecompose (uncovered.getType ())) {
1114
1093
SmallVector<Space, 4 > spaces;
1115
1094
Space::decompose (TC, uncovered.getType (), spaces);
1116
- diagnoseMissingCases (TC, Switch, RequiresDefault::No, Space (spaces));
1095
+ diagnoseMissingCases (TC, Switch,
1096
+ /* justNeedsDefault*/ false , Space (spaces));
1117
1097
} else {
1118
- diagnoseMissingCases (TC, Switch, Switch->getCases ().empty ()
1119
- ? RequiresDefault::EmptySwitchBody
1120
- : RequiresDefault::UncoveredSwitch,
1121
- Space ());
1098
+ diagnoseMissingCases (TC, Switch,
1099
+ /* justNeedsDefault*/ true , Space ());
1122
1100
}
1123
1101
return ;
1124
1102
}
@@ -1129,7 +1107,7 @@ namespace {
1129
1107
uncovered = Space (spaces);
1130
1108
}
1131
1109
1132
- diagnoseMissingCases (TC, Switch, RequiresDefault::No , uncovered,
1110
+ diagnoseMissingCases (TC, Switch, /* justNeedsDefault */ false , uncovered,
1133
1111
sawDowngradablePattern);
1134
1112
}
1135
1113
@@ -1161,15 +1139,8 @@ namespace {
1161
1139
}
1162
1140
}
1163
1141
1164
- enum class RequiresDefault {
1165
- No,
1166
- EmptySwitchBody,
1167
- UncoveredSwitch,
1168
- SpaceTooLarge,
1169
- };
1170
-
1171
1142
static void diagnoseMissingCases (TypeChecker &TC, const SwitchStmt *SS,
1172
- RequiresDefault defaultReason ,
1143
+ bool justNeedsDefault ,
1173
1144
Space uncovered,
1174
1145
bool sawDowngradablePattern = false ) {
1175
1146
SourceLoc startLoc = SS->getStartLoc ();
@@ -1178,30 +1149,20 @@ namespace {
1178
1149
llvm::SmallString<128 > buffer;
1179
1150
llvm::raw_svector_ostream OS (buffer);
1180
1151
1181
- switch (defaultReason) {
1182
- case RequiresDefault::EmptySwitchBody: {
1183
- OS << tok::kw_default << " :\n " << placeholder << " \n " ;
1184
- TC.diagnose (startLoc, diag::empty_switch_stmt)
1185
- .fixItInsert (endLoc, buffer.str ());
1186
- }
1187
- return ;
1188
- case RequiresDefault::UncoveredSwitch: {
1152
+ bool InEditor = TC.Context .LangOpts .DiagnosticsEditorMode ;
1153
+
1154
+ if (justNeedsDefault) {
1189
1155
OS << tok::kw_default << " :\n " << placeholder << " \n " ;
1190
- TC.diagnose (startLoc, diag::non_exhaustive_switch);
1191
- TC.diagnose (startLoc, diag::missing_several_cases, uncovered.isEmpty ())
1192
- .fixItInsert (endLoc, buffer.str ());
1193
- }
1194
- return ;
1195
- case RequiresDefault::SpaceTooLarge: {
1196
- OS << tok::kw_default << " :\n " << " <#fatalError()#>" << " \n " ;
1197
- TC.diagnose (startLoc, diag::cannot_prove_exhaustive_switch);
1198
- TC.diagnose (startLoc, diag::missing_several_cases, uncovered.isEmpty ())
1199
- .fixItInsert (endLoc, buffer.str ());
1200
- }
1156
+ if (SS->getCases ().empty ()) {
1157
+ TC.Context .Diags .diagnose (startLoc, diag::empty_switch_stmt)
1158
+ .fixItInsert (endLoc, buffer.str ());
1159
+ } else {
1160
+ TC.Context .Diags .diagnose (startLoc, diag::non_exhaustive_switch);
1161
+ TC.Context .Diags .diagnose (startLoc, diag::missing_several_cases,
1162
+ uncovered.isEmpty ()).fixItInsert (endLoc,
1163
+ buffer.str ());
1164
+ }
1201
1165
return ;
1202
- case RequiresDefault::No:
1203
- // Break out to diagnose below.
1204
- break ;
1205
1166
}
1206
1167
1207
1168
// If there's nothing else to diagnose, bail.
@@ -1228,7 +1189,7 @@ namespace {
1228
1189
//
1229
1190
// missing case '(.none, .some(_))'
1230
1191
// missing case '(.some(_), .none)'
1231
- if (TC. Context . LangOpts . DiagnosticsEditorMode ) {
1192
+ if (InEditor ) {
1232
1193
buffer.clear ();
1233
1194
SmallVector<Space, 8 > emittedSpaces;
1234
1195
for (auto &uncoveredSpace : uncovered.getSpaces ()) {
@@ -1251,7 +1212,7 @@ namespace {
1251
1212
TC.diagnose (startLoc, diag::missing_several_cases, false )
1252
1213
.fixItInsert (endLoc, buffer.str ());
1253
1214
} else {
1254
- TC.diagnose (startLoc, mainDiagType);
1215
+ TC.Context . Diags . diagnose (startLoc, mainDiagType);
1255
1216
1256
1217
SmallVector<Space, 8 > emittedSpaces;
1257
1218
for (auto &uncoveredSpace : uncovered.getSpaces ()) {
0 commit comments