@@ -115,11 +115,6 @@ namespace {
115
115
Identifier Head;
116
116
std::forward_list<Space> Spaces;
117
117
118
- // NB: This constant is arbitrary. Anecdotally, the Space Engine is
119
- // capable of efficiently handling Spaces of around size 200, but it would
120
- // potentially push an enormous fixit on the user.
121
- static const size_t MAX_SPACE_SIZE = 128 ;
122
-
123
118
size_t computeSize (TypeChecker &TC, const DeclContext *DC,
124
119
SmallPtrSetImpl<TypeBase *> &cache) const {
125
120
switch (getKind ()) {
@@ -250,10 +245,6 @@ namespace {
250
245
return computeSize (TC, DC, cache);
251
246
}
252
247
253
- static size_t getMaximumSize () {
254
- return MAX_SPACE_SIZE;
255
- }
256
-
257
248
bool isEmpty () const { return getKind () == SpaceKind::Empty; }
258
249
259
250
bool isAllowedButNotRequired () const {
@@ -895,103 +886,6 @@ namespace {
895
886
}
896
887
}
897
888
898
- // / Estimate how big is the search space that exhaustivity
899
- // / checker needs to cover, based on the total space and information
900
- // / from the `switch` statement itself. Some of the easy situations
901
- // / like `case .foo(let bar)` don't really contribute to the complexity
902
- // / of the search so their sub-space sizes could be excluded from
903
- // / consideration.
904
- // /
905
- // / \param total The total space to check.
906
- // / \param covered The space covered by the `case` statements in the switch.
907
- // /
908
- // / \returns The size of the search space exhastivity checker has to check.
909
- size_t estimateSearchSpaceSize (const Space &total, const Space &covered) {
910
- switch (PairSwitch (total.getKind (), covered.getKind ())) {
911
- PAIRCASE (SpaceKind::Type, SpaceKind::Type): {
912
- return total.getType ()->isEqual (covered.getType ())
913
- ? 0
914
- : total.getSize (TC, DC);
915
- }
916
- PAIRCASE (SpaceKind::Type, SpaceKind::Disjunct):
917
- PAIRCASE (SpaceKind::Type, SpaceKind::Constructor): {
918
- if (!Space::canDecompose (total.getType (), DC))
919
- break ;
920
-
921
- auto decomposition = Space::decompose (TC, DC, total.getType ());
922
- return estimateSearchSpaceSize (decomposition, covered);
923
- }
924
-
925
- PAIRCASE (SpaceKind::Disjunct, SpaceKind::Disjunct):
926
- PAIRCASE (SpaceKind::Disjunct, SpaceKind::Constructor): {
927
- auto &spaces = total.getSpaces ();
928
- return std::accumulate (spaces.begin (), spaces.end (), 0 ,
929
- [&](size_t totalSize, const Space &space) {
930
- return totalSize + estimateSearchSpaceSize (
931
- space, covered);
932
- });
933
- }
934
-
935
- // Search space size computation is not commutative, because it
936
- // tries to check if space on right-hand side is covering any
937
- // portion of the "total" space on the left.
938
- PAIRCASE (SpaceKind::Constructor, SpaceKind::Disjunct): {
939
- for (const auto &space : covered.getSpaces ()) {
940
- // enum E { case foo }
941
- // func bar(_ lhs: E, _ rhs: E) {
942
- // switch (lhs, rhs) {
943
- // case (_, _): break
944
- // }
945
- if (total == space)
946
- return 0 ;
947
-
948
- if (!space.isSubspace (total, TC, DC))
949
- continue ;
950
-
951
- if (estimateSearchSpaceSize (total, space) == 0 )
952
- return 0 ;
953
- }
954
- break ;
955
- }
956
-
957
- PAIRCASE (SpaceKind::Constructor, SpaceKind::Constructor): {
958
- if (total.getHead () != covered.getHead ())
959
- break ;
960
-
961
- auto &lhs = total.getSpaces ();
962
- auto &rhs = covered.getSpaces ();
963
-
964
- if (std::distance (lhs.begin (), lhs.end ()) !=
965
- std::distance (rhs.begin (), rhs.end ()))
966
- return total.getSize (TC, DC);
967
-
968
- auto i = lhs.begin ();
969
- auto j = rhs.begin ();
970
-
971
- size_t totalSize = 0 ;
972
- for (; i != lhs.end () && j != rhs.end (); ++i, ++j) {
973
- // The only light-weight checking we can do
974
- // is when sub-spaces on both sides are types
975
- // otherwise we'd have to decompose, which
976
- // is too heavy, so let's just return total
977
- // space size if such situation is detected.
978
- if (i->getKind () != SpaceKind::Type ||
979
- j->getKind () != SpaceKind::Type)
980
- return total.getSize (TC, DC);
981
-
982
- totalSize += estimateSearchSpaceSize (*i, *j);
983
- }
984
-
985
- return totalSize;
986
- }
987
-
988
- default :
989
- break ;
990
- }
991
-
992
- return total.getSize (TC, DC);
993
- }
994
-
995
889
void checkExhaustiveness (bool limitedChecking) {
996
890
// If the type of the scrutinee is uninhabited, we're already dead.
997
891
// Allow any well-typed patterns through.
@@ -1008,7 +902,6 @@ namespace {
1008
902
return ;
1009
903
}
1010
904
1011
- bool sawRedundantPattern = false ;
1012
905
const CaseStmt *unknownCase = nullptr ;
1013
906
SmallVector<Space, 4 > spaces;
1014
907
for (auto *caseBlock : Switch->getCases ()) {
@@ -1032,8 +925,6 @@ namespace {
1032
925
1033
926
if (!projection.isEmpty () &&
1034
927
projection.isSubspace (Space::forDisjunct (spaces), TC, DC)) {
1035
- sawRedundantPattern |= true ;
1036
-
1037
928
TC.diagnose (caseItem.getStartLoc (),
1038
929
diag::redundant_particular_case)
1039
930
.highlight (caseItem.getSourceRange ());
@@ -1058,18 +949,11 @@ namespace {
1058
949
Space totalSpace = Space::forType (subjectType, Identifier ());
1059
950
Space coveredSpace = Space::forDisjunct (spaces);
1060
951
1061
- const size_t searchSpaceSizeEstimate =
1062
- estimateSearchSpaceSize (totalSpace, coveredSpace);
1063
- if (searchSpaceSizeEstimate > Space::getMaximumSize ()) {
1064
- diagnoseCannotCheck (sawRedundantPattern, totalSpace, coveredSpace,
1065
- unknownCase);
1066
- return ;
1067
- }
1068
952
unsigned minusCount = 0 ;
1069
953
auto diff = totalSpace.minus (coveredSpace, TC, DC, &minusCount);
1070
954
if (!diff) {
1071
- diagnoseCannotCheck (sawRedundantPattern, totalSpace, coveredSpace ,
1072
- unknownCase);
955
+ diagnoseMissingCases (RequiresDefault::SpaceTooLarge, Space () ,
956
+ unknownCase);
1073
957
return ;
1074
958
}
1075
959
@@ -1115,26 +999,7 @@ namespace {
1115
999
UncoveredSwitch,
1116
1000
SpaceTooLarge,
1117
1001
};
1118
-
1119
- void diagnoseCannotCheck (const bool sawRedundantPattern,
1120
- const Space &totalSpace,
1121
- const Space &coveredSpace,
1122
- const CaseStmt *unknownCase) {
1123
- // Because the space is large or the check is too slow,
1124
- // we have to extend the size
1125
- // heuristic to compensate for actually exhaustively pattern matching
1126
- // over enormous spaces. In this case, if the covered space covers
1127
- // as much as the total space, and there were no duplicates, then we
1128
- // can assume the user did the right thing and that they don't need
1129
- // a 'default' to be inserted.
1130
- // FIXME: Do something sensible for non-frozen enums.
1131
- if (!sawRedundantPattern &&
1132
- coveredSpace.getSize (TC, DC) >= totalSpace.getSize (TC, DC))
1133
- return ;
1134
- diagnoseMissingCases (RequiresDefault::SpaceTooLarge, Space (),
1135
- unknownCase);
1136
- }
1137
-
1002
+
1138
1003
void diagnoseMissingCases (RequiresDefault defaultReason, Space uncovered,
1139
1004
const CaseStmt *unknownCase = nullptr ) {
1140
1005
SourceLoc startLoc = Switch->getStartLoc ();
0 commit comments