@@ -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);
@@ -3128,12 +3145,20 @@ void Serializer::writeDecl(const Decl *D) {
31283145 auto conformances = theStruct->getLocalConformances (
31293146 ConformanceLookupKind::All, nullptr );
31303147
3131- SmallVector<TypeID, 4 > inheritedTypes ;
3148+ SmallVector<TypeID, 4 > inheritedAndDependencyTypes ;
31323149 for (auto inherited : theStruct->getInherited ()) {
31333150 assert (!inherited.getType ()->hasArchetype ());
3134- inheritedTypes .push_back (addTypeRef (inherited.getType ()));
3151+ inheritedAndDependencyTypes .push_back (addTypeRef (inherited.getType ()));
31353152 }
31363153
3154+ llvm::SmallSetVector<Type, 4 > dependencyTypes;
3155+ for (Requirement req : theStruct->getGenericRequirements ()) {
3156+ collectDependenciesFromRequirement (dependencyTypes, req,
3157+ /* excluding*/ nullptr );
3158+ }
3159+ for (Type ty : dependencyTypes)
3160+ inheritedAndDependencyTypes.push_back (addTypeRef (ty));
3161+
31373162 uint8_t rawAccessLevel =
31383163 getRawStableAccessLevel (theStruct->getFormalAccess ());
31393164
@@ -3147,7 +3172,8 @@ void Serializer::writeDecl(const Decl *D) {
31473172 theStruct->getGenericEnvironment ()),
31483173 rawAccessLevel,
31493174 conformances.size (),
3150- inheritedTypes);
3175+ theStruct->getInherited ().size (),
3176+ inheritedAndDependencyTypes);
31513177
31523178
31533179 writeGenericParams (theStruct->getGenericParams ());
@@ -3175,6 +3201,11 @@ void Serializer::writeDecl(const Decl *D) {
31753201 for (const EnumElementDecl *nextElt : theEnum->getAllElements ()) {
31763202 if (!nextElt->hasAssociatedValues ())
31773203 continue ;
3204+ // FIXME: Types in the same module are still important for enums. It's
3205+ // possible an enum element has a payload that references a type
3206+ // declaration from the same module that can't be imported (for whatever
3207+ // reason). However, we need a more robust handling of deserialization
3208+ // dependencies that can handle circularities. rdar://problem/32359173
31783209 collectDependenciesFromType (dependencyTypes,
31793210 nextElt->getArgumentInterfaceType (),
31803211 /* excluding*/ theEnum->getParentModule ());
@@ -3219,11 +3250,28 @@ void Serializer::writeDecl(const Decl *D) {
32193250 auto conformances = theClass->getLocalConformances (
32203251 ConformanceLookupKind::NonInherited, nullptr );
32213252
3222- SmallVector<TypeID, 4 > inheritedTypes ;
3253+ SmallVector<TypeID, 4 > inheritedAndDependencyTypes ;
32233254 for (auto inherited : theClass->getInherited ()) {
32243255 assert (!inherited.getType ()->hasArchetype ());
3225- inheritedTypes.push_back (addTypeRef (inherited.getType ()));
3256+ inheritedAndDependencyTypes.push_back (addTypeRef (inherited.getType ()));
3257+ }
3258+
3259+ llvm::SmallSetVector<Type, 4 > dependencyTypes;
3260+ if (theClass->hasSuperclass ()) {
3261+ // FIXME: Nested types can still be a problem here: it's possible that (for
3262+ // whatever reason) they won't be able to be deserialized, in which case
3263+ // we'll be in trouble forming the actual superclass type. However, we
3264+ // need a more robust handling of deserialization dependencies that can
3265+ // handle circularities. rdar://problem/50835214
3266+ collectDependenciesFromType (dependencyTypes, theClass->getSuperclass (),
3267+ /* excluding*/ theClass);
3268+ }
3269+ for (Requirement req : theClass->getGenericRequirements ()) {
3270+ collectDependenciesFromRequirement (dependencyTypes, req,
3271+ /* excluding*/ nullptr );
32263272 }
3273+ for (Type ty : dependencyTypes)
3274+ inheritedAndDependencyTypes.push_back (addTypeRef (ty));
32273275
32283276 uint8_t rawAccessLevel =
32293277 getRawStableAccessLevel (theClass->getFormalAccess ());
@@ -3245,7 +3293,8 @@ void Serializer::writeDecl(const Decl *D) {
32453293 addTypeRef (theClass->getSuperclass ()),
32463294 rawAccessLevel,
32473295 conformances.size (),
3248- inheritedTypes);
3296+ theClass->getInherited ().size (),
3297+ inheritedAndDependencyTypes);
32493298
32503299 writeGenericParams (theClass->getGenericParams ());
32513300 writeMembers (id, theClass->getMembers (), true );
0 commit comments