Skip to content

Commit 3ea6635

Browse files
committed
[Sema] SpaceEngine: Improve handling of empty/non-reduced spaces in construtors/disjuncts
Eagerly remove empty (sub-)spaces from constructors and disjuncts to minimize number of operations required to check space coverage. Also return original constructor space while subtracting a pair of constructors, instead of disjunct, if subtraction of one of its sub-spaces produced the same space, this reduces the number of disjuncts in the path. Resolves: rdar://problem/39710335
1 parent 6723cc9 commit 3ea6635

File tree

2 files changed

+89
-5
lines changed

2 files changed

+89
-5
lines changed

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,18 @@ namespace {
231231
return Space(C);
232232
}
233233
static Space forDisjunct(ArrayRef<Space> SP) {
234-
if (SP.empty())
234+
SmallVector<Space, 4> spaces(SP.begin(), SP.end());
235+
spaces.erase(
236+
std::remove_if(spaces.begin(), spaces.end(),
237+
[](const Space &space) { return space.isEmpty(); }),
238+
spaces.end());
239+
240+
if (spaces.empty())
235241
return Space();
236-
if (SP.size() == 1)
237-
return SP.front();
238-
return Space(SP);
242+
if (spaces.size() == 1)
243+
return spaces.front();
244+
245+
return Space(spaces);
239246
}
240247

241248
bool operator==(const Space &other) const {
@@ -805,7 +812,23 @@ namespace {
805812
// into each parameter.
806813
SmallVector<Space, 4> copyParams(this->getSpaces().begin(),
807814
this->getSpaces().end());
808-
copyParams[idx] = s1.minus(s2, TC, DC);
815+
816+
auto reducedSpace = s1.minus(s2, TC, DC);
817+
// If one of the constructor parameters is empty it means
818+
// the whole constructor space is empty as well, so we can
819+
// safely skip it.
820+
if (reducedSpace.isEmpty())
821+
continue;
822+
823+
// If reduced produced the same space as original one, we
824+
// should return it directly instead of trying to create
825+
// a disjunction of its sub-spaces because nothing got reduced.
826+
// This is especially helpful when dealing with `unknown` case
827+
// in parameter positions.
828+
if (s1 == reducedSpace)
829+
return *this;
830+
831+
copyParams[idx] = reducedSpace;
809832
Space CS = Space::forConstructor(this->getType(), this->getHead(),
810833
this->canDowngradeToWarning(),
811834
copyParams);

test/Sema/rdar39710335.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
enum E1 {
4+
case a1
5+
case b1
6+
case c1
7+
case d1
8+
case e1
9+
case f1
10+
}
11+
12+
enum E2 {
13+
case a2, b2, c2, d2
14+
}
15+
16+
func foo(s: E1, style: E2) {
17+
switch (s, style) {
18+
case (.a1, .a2),
19+
(.a1, .d2),
20+
(.c1, .a2),
21+
(.c1, .d2),
22+
(.c1, .c2),
23+
(.a1, .c2):
24+
break
25+
26+
case (.a1, .b2),
27+
(.b1, .b2),
28+
(.c1, .b2):
29+
break
30+
31+
case (.b1, .a2),
32+
(.b1, .d2),
33+
(.b1, .c2):
34+
break
35+
36+
case (.e1, .a2),
37+
(.e1, .d2),
38+
(.e1, .c2):
39+
break
40+
41+
case (.e1, .b2):
42+
break
43+
44+
case (.d1, .a2),
45+
(.d1, .d2):
46+
47+
break
48+
49+
case (.d1, .b2):
50+
break
51+
52+
case (.d1, .c2):
53+
break
54+
55+
case (.f1, .a2),
56+
(.f1, .b2),
57+
(.f1, .c2),
58+
(.f1, .d2):
59+
break
60+
}
61+
}

0 commit comments

Comments
 (0)