|
13 | 13 | #include "llvm/ADT/StringSwitch.h"
|
14 | 14 | #include "swift/AST/Decl.h"
|
15 | 15 | #include "swift/AST/Module.h"
|
| 16 | +#include "swift/AST/ProtocolConformance.h" |
16 | 17 | #include "swift/Serialization/SerializedModuleLoader.h"
|
17 | 18 | #include "swift/SymbolGraphGen/SymbolGraphGen.h"
|
18 | 19 |
|
@@ -181,79 +182,33 @@ bool SymbolGraphASTWalker::walkToDeclPre(Decl *D, CharSourceRange Range) {
|
181 | 182 | // We want to add conformsTo relationships for all protocols implicitly
|
182 | 183 | // implied by those explicitly stated on the extension.
|
183 | 184 | //
|
184 |
| - // Thus, we have to expand two syntactic constructs: |
185 |
| - // * `protocol A: B, C { ... }` declarations, where those that still have |
186 |
| - // to be expanded are stored in `UnexpandedProtocols` |
187 |
| - // that still have to be expanded |
188 |
| - // * `typealias A = B & C` declarations, which are directly expanded to |
189 |
| - // unexpanded protocols in `HandleProtocolOrComposition` |
190 |
| - // |
191 |
| - // The expansion adds the base protocol to `Protocols` and calls |
192 |
| - // `HandleProtocolOrComposition` for the implied protocols. This process |
193 |
| - // continues until there is nothing left to expand (`UnexpandedProtocols` |
194 |
| - // is empty), because `HandleProtocolOrComposition` didn't add any new |
195 |
| - // unexpanded protocols. At that point, all direct and indirect |
196 |
| - // conformances are stored in `Protocols`. |
197 |
| - |
198 |
| - SmallVector<const ProtocolDecl *, 4> Protocols; |
| 185 | + // We start by collecting the conformances declared on the extension with |
| 186 | + // `getLocalConformances`. From there, we inspect each protocol for any |
| 187 | + // other protocols it inherits (whether stated explicitly or via a |
| 188 | + // composed protocol type alias) with `getInheritedProtocols`. Each new |
| 189 | + // protocol is added to `UnexpandedProtocols` until there are no new |
| 190 | + // protocols to add. At that point, all direct and indirect conformances |
| 191 | + // are stored in `Protocols`. |
| 192 | + |
| 193 | + SmallPtrSet<const ProtocolDecl *, 4> Protocols; |
199 | 194 | SmallVector<const ProtocolDecl *, 4> UnexpandedProtocols;
|
200 | 195 |
|
201 |
| - // Unwrap `UnexpandedCompositions` and add all unexpanded protocols to the |
202 |
| - // `UnexpandedProtocols` list for expansion. |
203 |
| - auto HandleProtocolOrComposition = [&](Type Ty) { |
204 |
| - if (const auto *Proto = |
205 |
| - dyn_cast_or_null<ProtocolDecl>(Ty->getAnyNominal())) { |
206 |
| - UnexpandedProtocols.push_back(Proto); |
207 |
| - return; |
208 |
| - } |
209 |
| - |
210 |
| - SmallVector<const ProtocolCompositionType *, 4> UnexpandedCompositions; |
211 |
| - |
212 |
| - if (const auto *Comp = Ty->getAs<ProtocolCompositionType>()) { |
213 |
| - UnexpandedCompositions.push_back(Comp); |
214 |
| - } else { |
215 |
| - llvm_unreachable("Expected ProtocolDecl or ProtocolCompositionType"); |
216 |
| - } |
217 |
| - |
218 |
| - while (!UnexpandedCompositions.empty()) { |
219 |
| - const auto *Comp = UnexpandedCompositions.pop_back_val(); |
220 |
| - for (const auto &Member : Comp->getMembers()) { |
221 |
| - if (const auto *Proto = |
222 |
| - dyn_cast_or_null<ProtocolDecl>(Member->getAnyNominal())) { |
223 |
| - Protocols.push_back(Proto); |
224 |
| - UnexpandedProtocols.push_back(Proto); |
225 |
| - } else if (const auto *Comp = |
226 |
| - Member->getAs<ProtocolCompositionType>()) { |
227 |
| - UnexpandedCompositions.push_back(Comp); |
228 |
| - } else { |
229 |
| - abort(); |
230 |
| - } |
231 |
| - } |
232 |
| - } |
233 |
| - }; |
234 |
| - |
235 | 196 | // Start the process with the conformances stated
|
236 | 197 | // explicitly on the extension.
|
237 |
| - for (const auto &InheritedLoc : Extension->getInherited()) { |
238 |
| - auto InheritedTy = InheritedLoc.getType(); |
239 |
| - if (!InheritedTy) { |
240 |
| - continue; |
241 |
| - } |
242 |
| - HandleProtocolOrComposition(InheritedTy); |
| 198 | + for (const auto *Conformance : Extension->getLocalConformances()) { |
| 199 | + UnexpandedProtocols.push_back(Conformance->getProtocol()); |
243 | 200 | }
|
244 | 201 |
|
245 | 202 | // "Recursively" expand the unexpanded list and populate
|
246 | 203 | // the expanded `Protocols` list (in an iterative manner).
|
247 | 204 | while (!UnexpandedProtocols.empty()) {
|
248 | 205 | const auto *Proto = UnexpandedProtocols.pop_back_val();
|
249 |
| - for (const auto &InheritedEntry : Proto->getInherited()) { |
250 |
| - auto InheritedTy = InheritedEntry.getType(); |
251 |
| - if (!InheritedTy) { |
252 |
| - continue; |
| 206 | + if (!Protocols.contains(Proto)) { |
| 207 | + for (const auto *InheritedProtocol : Proto->getInheritedProtocols()) { |
| 208 | + UnexpandedProtocols.push_back(InheritedProtocol); |
253 | 209 | }
|
254 |
| - HandleProtocolOrComposition(InheritedTy); |
| 210 | + Protocols.insert(Proto); |
255 | 211 | }
|
256 |
| - Protocols.push_back(Proto); |
257 | 212 | }
|
258 | 213 |
|
259 | 214 | // Record the expanded list of protocols.
|
|
0 commit comments