@@ -4783,11 +4783,31 @@ bool NominalTypeDecl::isResilient(ModuleDecl *M,
47834783 case ResilienceExpansion::Minimal:
47844784 return isResilient ();
47854785 case ResilienceExpansion::Maximal:
4786- // We consider this decl belongs to the module either it's currently
4787- // defined in this module or it's originally defined in this module, which
4788- // is specified by @_originallyDefinedIn
4789- return M != getModuleContext () && !isOriginallyDefinedIn (this , M) &&
4790- isResilient ();
4786+ // We can access declarations from the same module
4787+ // non-resiliently in a maximal context.
4788+ if (M == getModuleContext ()) {
4789+ return false ;
4790+ }
4791+ // If a protocol is originally declared in the current module, then we
4792+ // directly expose protocol witness tables and their contents for any
4793+ // conformances in the same module as symbols. If the protocol later
4794+ // moves, then we need to preserve those extra symbols from the home
4795+ // module by treating the protocol as if it was still defined in the same
4796+ // module.
4797+ //
4798+ // This logic does not and should not generally extend to other kinds of
4799+ // declaration. If a declaration moves to a new module with library
4800+ // evolution enabled, then even the original module has to access it
4801+ // according to the library evolution ABI. This is an ABI compatibility
4802+ // hack only for protocols. If you see other variations of `isResilient`
4803+ // that don't check `isOriginallyDefinedIn`, they are probably correct.
4804+ if (isa<ProtocolDecl>(this )
4805+ && isOriginallyDefinedIn (this , M)) {
4806+ return false ;
4807+ }
4808+ // Otherwise, we have to access the declaration resiliently if it's
4809+ // resilient anywhere.
4810+ return isResilient ();
47914811 }
47924812 llvm_unreachable (" bad resilience expansion" );
47934813}
0 commit comments