@@ -36,11 +36,6 @@ void ProtocolGraph::visitProtocols(ArrayRef<const ProtocolDecl *> protos) {
3636 }
3737}
3838
39- // / Return true if we know about this protocol.
40- bool ProtocolGraph::isKnownProtocol (const ProtocolDecl *proto) const {
41- return Info.count (proto) > 0 ;
42- }
43-
4439// / Look up information about a known protocol.
4540const ProtocolInfo &ProtocolGraph::getProtocolInfo (
4641 const ProtocolDecl *proto) const {
@@ -49,223 +44,23 @@ const ProtocolInfo &ProtocolGraph::getProtocolInfo(
4944 return found->second ;
5045}
5146
52- // / The "support" of a protocol P is the size of the transitive closure of
53- // / the singleton set {P} under protocol inheritance.
54- unsigned ProtocolGraph::getProtocolSupport (
55- const ProtocolDecl *proto) const {
56- return getProtocolInfo (proto).AllInherited .size () + 1 ;
57- }
58-
59- // / The "support" of a set S of protocols is the size of the transitive
60- // / closure of S under protocol inheritance. For example, if you start
61- // / with
62- // /
63- // / protocol P1 : P3 {}
64- // / protocol P2 : P3 {}
65- // / protocol P3 {}
66- // /
67- // / Then the "support" of P1 & P2 is 3 because |P1 & P2 & P3| = 3.
68- // /
69- // / The \p protos array must be sorted in canonical order and
70- // / permanently-allocated; one safe choice is to use the return value of
71- // / Symbol::getProtocols().
72- unsigned ProtocolGraph::getProtocolSupport (
73- ArrayRef<const ProtocolDecl *> protos) const {
74- auto found = Support.find (protos);
75- if (found != Support.end ())
76- return found->second ;
77-
78- unsigned result;
79- if (protos.size () == 1 ) {
80- result = getProtocolSupport (protos[0 ]);
81- } else {
82- llvm::DenseSet<const ProtocolDecl *> visited;
83- for (const auto *proto : protos) {
84- visited.insert (proto);
85- for (const auto *inheritedProto : getProtocolInfo (proto).AllInherited )
86- visited.insert (inheritedProto);
87- }
88-
89- result = visited.size ();
90- }
91-
92- const_cast <ProtocolGraph *>(this )->Support [protos] = result;
93- return result;
94- }
95-
9647// / Record information about a protocol if we have no seen it yet.
9748void ProtocolGraph::addProtocol (const ProtocolDecl *proto,
9849 bool initialComponent) {
9950 if (Info.count (proto) > 0 )
10051 return ;
10152
102- Info[proto] = {proto->getInheritedProtocols (),
103- proto->getAssociatedTypeMembers (),
104- proto->getProtocolDependencies (),
105- initialComponent};
53+ Info[proto] = {initialComponent};
10654 Protocols.push_back (proto);
10755}
10856
109- // / Record information about all protocols transtively referenced
110- // / from protocol requirement signatures.
111- void ProtocolGraph::computeTransitiveClosure () {
57+ // / Compute everything in the right order.
58+ void ProtocolGraph::compute () {
11259 unsigned i = 0 ;
11360 while (i < Protocols.size ()) {
11461 auto *proto = Protocols[i++];
115- for (auto *proto : getProtocolInfo (proto).Dependencies ) {
116- addProtocol (proto, /* initialComponent=*/ false );
117- }
118- }
119- }
120-
121- // / See ProtocolGraph::compareProtocols() for the definition of this linear
122- // / order.
123- void ProtocolGraph::computeLinearOrder () {
124- for (const auto *proto : Protocols) {
125- (void ) computeProtocolDepth (proto);
126- }
127-
128- std::sort (
129- Protocols.begin (), Protocols.end (),
130- [&](const ProtocolDecl *lhs,
131- const ProtocolDecl *rhs) -> bool {
132- const auto &lhsInfo = getProtocolInfo (lhs);
133- const auto &rhsInfo = getProtocolInfo (rhs);
134-
135- // protocol Base {} // depth 1
136- // protocol Derived : Base {} // depth 2
137- //
138- // Derived < Base in the linear order.
139- if (lhsInfo.Depth != rhsInfo.Depth )
140- return lhsInfo.Depth > rhsInfo.Depth ;
141-
142- return TypeDecl::compare (lhs, rhs) < 0 ;
143- });
144-
145- for (unsigned i : indices (Protocols)) {
146- Info[Protocols[i]].Index = i;
147- }
148-
149- if (Debug) {
150- for (const auto *proto : Protocols) {
151- const auto &info = getProtocolInfo (proto);
152- llvm::dbgs () << " @ Protocol " << proto->getName ()
153- << " Depth=" << info.Depth
154- << " Index=" << info.Index << " \n " ;
155- }
156- }
157- }
158-
159- // / Update each ProtocolInfo's AssociatedTypes vector to add all associated
160- // / types from all transitively inherited protocols.
161- void ProtocolGraph::computeInheritedAssociatedTypes () {
162- // Visit protocols in reverse order, so that if P inherits from Q and
163- // Q inherits from R, we first visit R, then Q, then P, ensuring that
164- // R's associated types are added to P's list, etc.
165- for (const auto *proto : llvm::reverse (Protocols)) {
166- auto &info = Info[proto];
167-
168- for (const auto *inherited : info.AllInherited ) {
169- for (auto *inheritedType : getProtocolInfo (inherited).AssociatedTypes ) {
170- info.InheritedAssociatedTypes .push_back (inheritedType);
171- }
62+ for (auto *depProto : proto->getProtocolDependencies ()) {
63+ addProtocol (depProto, /* initialComponent=*/ false );
17264 }
17365 }
174- }
175-
176- // Update each protocol's AllInherited vector to add all transitively
177- // inherited protocols.
178- void ProtocolGraph::computeInheritedProtocols () {
179- // Visit protocols in reverse order, so that if P inherits from Q and
180- // Q inherits from R, we first visit R, then Q, then P, ensuring that
181- // R's inherited protocols are added to P's list, etc.
182- for (const auto *proto : llvm::reverse (Protocols)) {
183- auto &info = Info[proto];
184-
185- // We might inherit the same protocol multiple times due to diamond
186- // inheritance, so make sure we only add each protocol once.
187- llvm::SmallDenseSet<const ProtocolDecl *, 4 > visited;
188- visited.insert (proto);
189-
190- for (const auto *inherited : info.Inherited ) {
191- // Add directly-inherited protocols.
192- if (!visited.insert (inherited).second )
193- continue ;
194- info.AllInherited .push_back (inherited);
195-
196- // Add indirectly-inherited protocols.
197- for (auto *inheritedType : getProtocolInfo (inherited).AllInherited ) {
198- if (!visited.insert (inheritedType).second )
199- continue ;
200-
201- info.AllInherited .push_back (inheritedType);
202- }
203- }
204- }
205- }
206-
207- // / Recursively compute the 'depth' of a protocol, which is inductively defined
208- // / as one greater than the depth of all inherited protocols, with a protocol
209- // / that does not inherit any other protocol having a depth of one.
210- unsigned ProtocolGraph::computeProtocolDepth (const ProtocolDecl *proto) {
211- auto &info = Info[proto];
212-
213- if (info.Mark ) {
214- // Already computed, or we have a cycle. Cycles are diagnosed
215- // elsewhere in the type checker, so we don't have to do
216- // anything here.
217- return info.Depth ;
218- }
219-
220- info.Mark = true ;
221- unsigned depth = 0 ;
222-
223- for (auto *inherited : info.Inherited ) {
224- unsigned inheritedDepth = computeProtocolDepth (inherited);
225- depth = std::max (inheritedDepth, depth);
226- }
227-
228- depth++;
229-
230- info.Depth = depth;
231- return depth;
232- }
233-
234- // / Compute everything in the right order.
235- void ProtocolGraph::compute () {
236- computeTransitiveClosure ();
237- computeLinearOrder ();
238- computeInheritedProtocols ();
239- computeInheritedAssociatedTypes ();
240- }
241-
242- // / Defines a linear order with the property that if a protocol P inherits
243- // / from another protocol Q, then P < Q. (The converse cannot be true, since
244- // / this is a linear order.)
245- // /
246- // / We first compare the 'support' of a protocol, which is defined in
247- // / ProtocolGraph::getProtocolSupport() above.
248- // /
249- // / If two protocols have the same support, the tie is broken by the standard
250- // / TypeDecl::compare().
251- int ProtocolGraph::compareProtocols (const ProtocolDecl *lhs,
252- const ProtocolDecl *rhs) const {
253- unsigned lhsSupport = getProtocolSupport (lhs);
254- unsigned rhsSupport = getProtocolSupport (rhs);
255-
256- if (lhsSupport != rhsSupport)
257- return rhsSupport - lhsSupport;
258-
259- return TypeDecl::compare (lhs, rhs);
260- }
261-
262- // / Returns if \p thisProto transitively inherits from \p otherProto.
263- // /
264- // / The result is false if the two protocols are equal.
265- bool ProtocolGraph::inheritsFrom (const ProtocolDecl *thisProto,
266- const ProtocolDecl *otherProto) const {
267- const auto &info = getProtocolInfo (thisProto);
268- return std::find (info.AllInherited .begin (),
269- info.AllInherited .end (),
270- otherProto) != info.AllInherited .end ();
271- }
66+ }
0 commit comments