@@ -2697,22 +2697,39 @@ void Serializer::writeForeignErrorConvention(const ForeignErrorConvention &fec){
26972697// / - \p decl is declared in an extension of a type that depends on
26982698// / \p problemContext
26992699static bool contextDependsOn (const NominalTypeDecl *decl,
2700- const ModuleDecl *problemModule) {
2701- return decl->getParentModule () == problemModule;
2700+ const DeclContext *problemContext) {
2701+ SmallPtrSet<const ExtensionDecl *, 8 > seenExtensionDCs;
2702+
2703+ const DeclContext *dc = decl;
2704+ do {
2705+ if (dc == problemContext)
2706+ return true ;
2707+
2708+ if (auto *extension = dyn_cast<ExtensionDecl>(dc)) {
2709+ if (extension->isChildContextOf (problemContext))
2710+ return true ;
2711+
2712+ // Avoid cycles when Left.Nested depends on Right.Nested somehow.
2713+ bool isNewlySeen = seenExtensionDCs.insert (extension).second ;
2714+ if (!isNewlySeen)
2715+ break ;
2716+ dc = extension->getSelfNominalTypeDecl ();
2717+
2718+ } else {
2719+ dc = dc->getParent ();
2720+ }
2721+ } while (dc);
2722+
2723+ return false ;
27022724}
27032725
27042726static void collectDependenciesFromType (llvm::SmallSetVector<Type, 4 > &seen,
27052727 Type ty,
2706- const ModuleDecl *excluding) {
2728+ const DeclContext *excluding) {
27072729 ty.visit ([&](Type next) {
27082730 auto *nominal = next->getAnyNominal ();
27092731 if (!nominal)
27102732 return ;
2711- // FIXME: Types in the same module are still important for enums. It's
2712- // possible an enum element has a payload that references a type declaration
2713- // from the same module that can't be imported (for whatever reason).
2714- // However, we need a more robust handling of deserialization dependencies
2715- // that can handle circularities. rdar://problem/32359173
27162733 if (contextDependsOn (nominal, excluding))
27172734 return ;
27182735 seen.insert (nominal->getDeclaredInterfaceType ());
@@ -2722,7 +2739,7 @@ static void collectDependenciesFromType(llvm::SmallSetVector<Type, 4> &seen,
27222739static void
27232740collectDependenciesFromRequirement (llvm::SmallSetVector<Type, 4 > &seen,
27242741 const Requirement &req,
2725- const ModuleDecl *excluding) {
2742+ const DeclContext *excluding) {
27262743 collectDependenciesFromType (seen, req.getFirstType (), excluding);
27272744 if (req.getKind () != RequirementKind::Layout)
27282745 collectDependenciesFromType (seen, req.getSecondType (), excluding);
@@ -3123,12 +3140,20 @@ void Serializer::writeDecl(const Decl *D) {
31233140 auto conformances = theStruct->getLocalConformances (
31243141 ConformanceLookupKind::All, nullptr );
31253142
3126- SmallVector<TypeID, 4 > inheritedTypes ;
3143+ SmallVector<TypeID, 4 > inheritedAndDependencyTypes ;
31273144 for (auto inherited : theStruct->getInherited ()) {
31283145 assert (!inherited.getType ()->hasArchetype ());
3129- inheritedTypes .push_back (addTypeRef (inherited.getType ()));
3146+ inheritedAndDependencyTypes .push_back (addTypeRef (inherited.getType ()));
31303147 }
31313148
3149+ llvm::SmallSetVector<Type, 4 > dependencyTypes;
3150+ for (Requirement req : theStruct->getGenericRequirements ()) {
3151+ collectDependenciesFromRequirement (dependencyTypes, req,
3152+ /* excluding*/ nullptr );
3153+ }
3154+ for (Type ty : dependencyTypes)
3155+ inheritedAndDependencyTypes.push_back (addTypeRef (ty));
3156+
31323157 uint8_t rawAccessLevel =
31333158 getRawStableAccessLevel (theStruct->getFormalAccess ());
31343159
@@ -3142,7 +3167,8 @@ void Serializer::writeDecl(const Decl *D) {
31423167 theStruct->getGenericEnvironment ()),
31433168 rawAccessLevel,
31443169 conformances.size (),
3145- inheritedTypes);
3170+ theStruct->getInherited ().size (),
3171+ inheritedAndDependencyTypes);
31463172
31473173
31483174 writeGenericParams (theStruct->getGenericParams ());
@@ -3170,6 +3196,11 @@ void Serializer::writeDecl(const Decl *D) {
31703196 for (const EnumElementDecl *nextElt : theEnum->getAllElements ()) {
31713197 if (!nextElt->hasAssociatedValues ())
31723198 continue ;
3199+ // FIXME: Types in the same module are still important for enums. It's
3200+ // possible an enum element has a payload that references a type
3201+ // declaration from the same module that can't be imported (for whatever
3202+ // reason). However, we need a more robust handling of deserialization
3203+ // dependencies that can handle circularities. rdar://problem/32359173
31733204 collectDependenciesFromType (dependencyTypes,
31743205 nextElt->getArgumentInterfaceType (),
31753206 /* excluding*/ theEnum->getParentModule ());
@@ -3214,11 +3245,28 @@ void Serializer::writeDecl(const Decl *D) {
32143245 auto conformances = theClass->getLocalConformances (
32153246 ConformanceLookupKind::NonInherited, nullptr );
32163247
3217- SmallVector<TypeID, 4 > inheritedTypes ;
3248+ SmallVector<TypeID, 4 > inheritedAndDependencyTypes ;
32183249 for (auto inherited : theClass->getInherited ()) {
32193250 assert (!inherited.getType ()->hasArchetype ());
3220- inheritedTypes.push_back (addTypeRef (inherited.getType ()));
3251+ inheritedAndDependencyTypes.push_back (addTypeRef (inherited.getType ()));
3252+ }
3253+
3254+ llvm::SmallSetVector<Type, 4 > dependencyTypes;
3255+ if (theClass->hasSuperclass ()) {
3256+ // FIXME: Nested types can still be a problem here: it's possible that (for
3257+ // whatever reason) they won't be able to be deserialized, in which case
3258+ // we'll be in trouble forming the actual superclass type. However, we
3259+ // need a more robust handling of deserialization dependencies that can
3260+ // handle circularities. rdar://problem/50835214
3261+ collectDependenciesFromType (dependencyTypes, theClass->getSuperclass (),
3262+ /* excluding*/ theClass);
3263+ }
3264+ for (Requirement req : theClass->getGenericRequirements ()) {
3265+ collectDependenciesFromRequirement (dependencyTypes, req,
3266+ /* excluding*/ nullptr );
32213267 }
3268+ for (Type ty : dependencyTypes)
3269+ inheritedAndDependencyTypes.push_back (addTypeRef (ty));
32223270
32233271 uint8_t rawAccessLevel =
32243272 getRawStableAccessLevel (theClass->getFormalAccess ());
@@ -3240,7 +3288,8 @@ void Serializer::writeDecl(const Decl *D) {
32403288 addTypeRef (theClass->getSuperclass ()),
32413289 rawAccessLevel,
32423290 conformances.size (),
3243- inheritedTypes);
3291+ theClass->getInherited ().size (),
3292+ inheritedAndDependencyTypes);
32443293
32453294 writeGenericParams (theClass->getGenericParams ());
32463295 writeMembers (id, theClass->getMembers (), true );
0 commit comments