@@ -5956,6 +5956,65 @@ static void addAttributesForActorIsolation(ValueDecl *value,
59565956 }
59575957}
59585958
5959+ // / Determine whether there is a SendableMetatype conformance that requires that the nominal type
5960+ // / be nonisolated (preventing @MainActor inference).
5961+ static bool sendableConformanceRequiresNonisolated (NominalTypeDecl *nominal) {
5962+ ASTContext &ctx = nominal->getASTContext ();
5963+ if (!ctx.LangOpts .hasFeature (Feature::SendableProhibitsMainActorInference))
5964+ return false ;
5965+
5966+ if (isa<ProtocolDecl>(nominal))
5967+ return false ;
5968+
5969+ auto sendable = ctx.getProtocol (KnownProtocolKind::Sendable);
5970+ auto sendableMetatype = ctx.getProtocol (KnownProtocolKind::SendableMetatype);
5971+ if (!sendableMetatype)
5972+ return false ;
5973+
5974+ // Check whether any of the explicit conformances is to a
5975+ // SendableMetatype-inheriting protocol. We exclude direct conformance to
5976+ // Sendable here, because a global-actor-isolated type is implicitly Sendable,
5977+ // and writing Sendable explicitly
5978+ InvertibleProtocolSet inverses;
5979+ bool anyObject = false ;
5980+ auto inherited = getDirectlyInheritedNominalTypeDecls (
5981+ nominal, inverses, anyObject);
5982+ for (const auto &entry : inherited) {
5983+ auto proto = dyn_cast<ProtocolDecl>(entry.Item );
5984+ if (proto && proto != sendable && proto->inheritsFrom (sendableMetatype))
5985+ return true ;
5986+ }
5987+
5988+ // Check for member or extension macros that define conformances to
5989+ // SendableMetatype-inheriting protocols.
5990+ bool requiresNonisolated = false ;
5991+ auto checkMacro = [&](MacroRole role, MacroDecl *macro) {
5992+ if (!macro || requiresNonisolated)
5993+ return ;
5994+
5995+ SmallVector<ProtocolDecl *, 2 > conformances;
5996+ macro->getIntroducedConformances (nominal, role, conformances);
5997+ for (auto proto : conformances) {
5998+ if (proto == sendableMetatype || proto->inheritsFrom (sendableMetatype)) {
5999+ requiresNonisolated = true ;
6000+ break ;
6001+ }
6002+ }
6003+ };
6004+
6005+ nominal->forEachAttachedMacro (
6006+ MacroRole::Member,
6007+ [&](CustomAttr * attr, MacroDecl *macro) {
6008+ checkMacro (MacroRole::Member, macro);
6009+ });
6010+ nominal->forEachAttachedMacro (
6011+ MacroRole::Extension,
6012+ [&](CustomAttr * attr, MacroDecl *macro) {
6013+ checkMacro (MacroRole::Extension, macro);
6014+ });
6015+ return requiresNonisolated;
6016+ }
6017+
59596018// / Determine the default isolation and isolation source for this declaration,
59606019// / which may still be overridden by other inference rules.
59616020static std::tuple<InferredActorIsolation, ValueDecl *,
@@ -5975,24 +6034,34 @@ computeDefaultInferredActorIsolation(ValueDecl *value) {
59756034 auto *dc = value->getInnermostDeclContext ();
59766035 while (dc && !inActorContext) {
59776036 if (auto *nominal = dc->getSelfNominalTypeDecl ()) {
5978- inActorContext = nominal->isAnyActor ();
6037+ if (nominal->isAnyActor ())
6038+ return {};
59796039 }
59806040 dc = dc->getParent ();
59816041 }
59826042
5983- if (!inActorContext) {
5984- // FIXME: deinit should be implicitly MainActor too.
5985- if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
5986- isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
5987- isa<ConstructorDecl>(value)) {
6043+ // If this is or is a non-type member of a nominal type that conforms to a
6044+ // SendableMetatype-inheriting protocol in its primary definition, disable
6045+ // @MainActor inference.
6046+ auto nominalTypeDecl = dyn_cast<NominalTypeDecl>(value);
6047+ if (!nominalTypeDecl && !isa<TypeDecl>(value)) {
6048+ nominalTypeDecl = value->getDeclContext ()->getSelfNominalTypeDecl ();
6049+ }
6050+ if (nominalTypeDecl &&
6051+ sendableConformanceRequiresNonisolated (nominalTypeDecl))
6052+ return { };
6053+
6054+ // FIXME: deinit should be implicitly MainActor too.
6055+ if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
6056+ isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
6057+ isa<ConstructorDecl>(value)) {
59886058 // Preconcurrency here is used to stage the diagnostics
59896059 // when users select `@MainActor` default isolation with
59906060 // non-strict concurrency modes (pre Swift 6).
59916061 auto isolation =
59926062 ActorIsolation::forGlobalActor (globalActor)
59936063 .withPreconcurrency (!ctx.LangOpts .isSwiftVersionAtLeast (6 ));
59946064 return {{{isolation, {}}, nullptr , {}}};
5995- }
59966065 }
59976066
59986067 return {};
0 commit comments