@@ -5956,6 +5956,65 @@ static void addAttributesForActorIsolation(ValueDecl *value,
5956
5956
}
5957
5957
}
5958
5958
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
+
5959
6018
// / Determine the default isolation and isolation source for this declaration,
5960
6019
// / which may still be overridden by other inference rules.
5961
6020
static std::tuple<InferredActorIsolation, ValueDecl *,
@@ -5975,24 +6034,34 @@ computeDefaultInferredActorIsolation(ValueDecl *value) {
5975
6034
auto *dc = value->getInnermostDeclContext ();
5976
6035
while (dc && !inActorContext) {
5977
6036
if (auto *nominal = dc->getSelfNominalTypeDecl ()) {
5978
- inActorContext = nominal->isAnyActor ();
6037
+ if (nominal->isAnyActor ())
6038
+ return {};
5979
6039
}
5980
6040
dc = dc->getParent ();
5981
6041
}
5982
6042
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)) {
5988
6058
// Preconcurrency here is used to stage the diagnostics
5989
6059
// when users select `@MainActor` default isolation with
5990
6060
// non-strict concurrency modes (pre Swift 6).
5991
6061
auto isolation =
5992
6062
ActorIsolation::forGlobalActor (globalActor)
5993
6063
.withPreconcurrency (!ctx.LangOpts .isSwiftVersionAtLeast (6 ));
5994
6064
return {{{isolation, {}}, nullptr , {}}};
5995
- }
5996
6065
}
5997
6066
5998
6067
return {};
0 commit comments