Skip to content

Commit 960c1b0

Browse files
committed
Sema: Performance optimization for associated type solver
Don't explore parts of the solution space that would lead to a worse solution than what we already have.
1 parent 96b6e9e commit 960c1b0

File tree

2 files changed

+162
-7
lines changed

2 files changed

+162
-7
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2956,6 +2956,14 @@ void AssociatedTypeInference::findSolutionsRec(
29562956
unsigned numTypeWitnesses,
29572957
unsigned numValueWitnessesInProtocolExtensions,
29582958
unsigned reqDepth) {
2959+
// If this solution is going to be worse than what we've already recorded,
2960+
// give up now.
2961+
if (!solutions.empty() &&
2962+
solutions.front().NumValueWitnessesInProtocolExtensions
2963+
< numValueWitnessesInProtocolExtensions) {
2964+
return;
2965+
}
2966+
29592967
using TypeWitnessesScope = decltype(typeWitnesses)::ScopeTy;
29602968

29612969
// If we hit the last requirement, record and check this solution.
@@ -3089,6 +3097,13 @@ void AssociatedTypeInference::findSolutionsRec(
30893097
solution.NumValueWitnessesInProtocolExtensions
30903098
= numValueWitnessesInProtocolExtensions;
30913099

3100+
// If this solution was clearly better than the previous best solution,
3101+
// swap them.
3102+
if (solutionList.back().NumValueWitnessesInProtocolExtensions
3103+
< solutionList.front().NumValueWitnessesInProtocolExtensions) {
3104+
std::swap(solutionList.front(), solutionList.back());
3105+
}
3106+
30923107
// We're done recording the solution.
30933108
return;
30943109
}
@@ -3441,15 +3456,10 @@ bool AssociatedTypeInference::findBestSolution(
34413456
if (solutions.empty()) return true;
34423457
if (solutions.size() == 1) return false;
34433458

3444-
// Find the smallest number of value witnesses found in protocol extensions.
3445-
// FIXME: This is a silly heuristic that should go away.
3459+
// The solution at the front has the smallest number of value witnesses found
3460+
// in protocol extensions, by construction.
34463461
unsigned bestNumValueWitnessesInProtocolExtensions
34473462
= solutions.front().NumValueWitnessesInProtocolExtensions;
3448-
for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
3449-
bestNumValueWitnessesInProtocolExtensions
3450-
= std::min(bestNumValueWitnessesInProtocolExtensions,
3451-
solutions[i].NumValueWitnessesInProtocolExtensions);
3452-
}
34533463

34543464
// Erase any solutions with more value witnesses in protocol
34553465
// extensions than the best.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// Inspired by GRDB.swift.
4+
5+
protocol P {
6+
associatedtype A
7+
associatedtype B
8+
func f1(_: A)
9+
func f2(_: A)
10+
func f3(_: A)
11+
func f4(_: A)
12+
func f5(_: A)
13+
func f6(_: A)
14+
func f7(_: A)
15+
func f8(_: A)
16+
func f9(_: A)
17+
func f10(_: A)
18+
func f11(_: A)
19+
func f12(_: A)
20+
func f13(_: A)
21+
func f14(_: A)
22+
func f15(_: A)
23+
func f16(_: B)
24+
func f17(_: B)
25+
func f18(_: B)
26+
func f19(_: B)
27+
func f20(_: B)
28+
func f21(_: B)
29+
func f22(_: B)
30+
func f23(_: B)
31+
func f24(_: B)
32+
func f25(_: B)
33+
func f26(_: B)
34+
func f27(_: B)
35+
func f28(_: B)
36+
func f29(_: B)
37+
func f30(_: B)
38+
func f31(_: B)
39+
func f32(_: B)
40+
}
41+
42+
extension P {
43+
func f1(_: A) {}
44+
func f2(_: A) {}
45+
func f3(_: A) {}
46+
func f4(_: A) {}
47+
func f5(_: A) {}
48+
func f6(_: A) {}
49+
func f7(_: A) {}
50+
func f8(_: A) {}
51+
func f9(_: A) {}
52+
func f10(_: A) {}
53+
func f11(_: A) {}
54+
func f12(_: A) {}
55+
func f13(_: A) {}
56+
func f14(_: A) {}
57+
func f15(_: A) {}
58+
func f16(_: A) {}
59+
func f17(_: A) {}
60+
func f18(_: A) {}
61+
func f19(_: A) {}
62+
func f20(_: A) {}
63+
func f21(_: A) {}
64+
func f22(_: A) {}
65+
func f23(_: A) {}
66+
func f24(_: A) {}
67+
func f25(_: A) {}
68+
func f26(_: A) {}
69+
func f27(_: A) {}
70+
func f28(_: A) {}
71+
func f29(_: A) {}
72+
func f30(_: A) {}
73+
func f31(_: A) {}
74+
func f32(_: A) {}
75+
}
76+
77+
extension P {
78+
func f1(_: B) {}
79+
func f2(_: B) {}
80+
func f3(_: B) {}
81+
func f4(_: B) {}
82+
func f5(_: B) {}
83+
func f6(_: B) {}
84+
func f7(_: B) {}
85+
func f8(_: B) {}
86+
func f9(_: B) {}
87+
func f10(_: B) {}
88+
func f11(_: B) {}
89+
func f12(_: B) {}
90+
func f13(_: B) {}
91+
func f14(_: B) {}
92+
func f15(_: B) {}
93+
func f16(_: B) {}
94+
func f17(_: B) {}
95+
func f18(_: B) {}
96+
func f19(_: B) {}
97+
func f20(_: B) {}
98+
func f21(_: B) {}
99+
func f22(_: B) {}
100+
func f23(_: B) {}
101+
func f24(_: B) {}
102+
func f25(_: B) {}
103+
func f26(_: B) {}
104+
func f27(_: B) {}
105+
func f28(_: B) {}
106+
func f29(_: B) {}
107+
func f30(_: B) {}
108+
func f31(_: B) {}
109+
func f32(_: B) {}
110+
}
111+
112+
struct S: P {
113+
func f1(_: Int) {}
114+
func f2(_: Int) {}
115+
func f3(_: Int) {}
116+
func f4(_: Int) {}
117+
func f5(_: Int) {}
118+
func f6(_: Int) {}
119+
func f7(_: Int) {}
120+
func f8(_: Int) {}
121+
func f9(_: Int) {}
122+
func f10(_: Int) {}
123+
func f11(_: Int) {}
124+
func f12(_: Int) {}
125+
func f13(_: Int) {}
126+
func f14(_: Int) {}
127+
func f15(_: Int) {}
128+
func f16(_: Int) {}
129+
func f17(_: Int) {}
130+
func f18(_: Int) {}
131+
func f19(_: Int) {}
132+
func f20(_: Int) {}
133+
func f21(_: Int) {}
134+
func f22(_: Int) {}
135+
func f23(_: Int) {}
136+
func f24(_: Int) {}
137+
func f25(_: Int) {}
138+
func f26(_: Int) {}
139+
func f27(_: Int) {}
140+
func f28(_: Int) {}
141+
func f29(_: Int) {}
142+
func f30(_: Int) {}
143+
func f31(_: Int) {}
144+
func f32(_: Int) {}
145+
}

0 commit comments

Comments
 (0)