@@ -4783,11 +4783,31 @@ bool NominalTypeDecl::isResilient(ModuleDecl *M,
4783
4783
case ResilienceExpansion::Minimal:
4784
4784
return isResilient ();
4785
4785
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 ();
4791
4811
}
4792
4812
llvm_unreachable (" bad resilience expansion" );
4793
4813
}
0 commit comments