|
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