@@ -5936,6 +5936,65 @@ static void addAttributesForActorIsolation(ValueDecl *value,
5936
5936
}
5937
5937
}
5938
5938
5939
+ // / Determine whether there is a SendableMetatype conformance that requires that the nominal type
5940
+ // / be nonisolated (preventing @MainActor inference).
5941
+ static bool sendableConformanceRequiresNonisolated (NominalTypeDecl *nominal) {
5942
+ ASTContext &ctx = nominal->getASTContext ();
5943
+ if (!ctx.LangOpts .hasFeature (Feature::SendableProhibitsMainActorInference))
5944
+ return false ;
5945
+
5946
+ if (isa<ProtocolDecl>(nominal))
5947
+ return false ;
5948
+
5949
+ auto sendable = ctx.getProtocol (KnownProtocolKind::Sendable);
5950
+ auto sendableMetatype = ctx.getProtocol (KnownProtocolKind::SendableMetatype);
5951
+ if (!sendableMetatype)
5952
+ return false ;
5953
+
5954
+ // Check whether any of the explicit conformances is to a
5955
+ // SendableMetatype-inheriting protocol. We exclude direct conformance to
5956
+ // Sendable here, because a global-actor-isolated type is implicitly Sendable,
5957
+ // and writing Sendable explicitly
5958
+ InvertibleProtocolSet inverses;
5959
+ bool anyObject = false ;
5960
+ auto inherited = getDirectlyInheritedNominalTypeDecls (
5961
+ nominal, inverses, anyObject);
5962
+ for (const auto &entry : inherited) {
5963
+ auto proto = dyn_cast<ProtocolDecl>(entry.Item );
5964
+ if (proto && proto != sendable && proto->inheritsFrom (sendableMetatype))
5965
+ return true ;
5966
+ }
5967
+
5968
+ // Check for member or extension macros that define conformances to
5969
+ // SendableMetatype-inheriting protocols.
5970
+ bool requiresNonisolated = false ;
5971
+ auto checkMacro = [&](MacroRole role, MacroDecl *macro) {
5972
+ if (!macro || requiresNonisolated)
5973
+ return ;
5974
+
5975
+ SmallVector<ProtocolDecl *, 2 > conformances;
5976
+ macro->getIntroducedConformances (nominal, role, conformances);
5977
+ for (auto proto : conformances) {
5978
+ if (proto == sendableMetatype || proto->inheritsFrom (sendableMetatype)) {
5979
+ requiresNonisolated = true ;
5980
+ break ;
5981
+ }
5982
+ }
5983
+ };
5984
+
5985
+ nominal->forEachAttachedMacro (
5986
+ MacroRole::Member,
5987
+ [&](CustomAttr * attr, MacroDecl *macro) {
5988
+ checkMacro (MacroRole::Member, macro);
5989
+ });
5990
+ nominal->forEachAttachedMacro (
5991
+ MacroRole::Extension,
5992
+ [&](CustomAttr * attr, MacroDecl *macro) {
5993
+ checkMacro (MacroRole::Extension, macro);
5994
+ });
5995
+ return requiresNonisolated;
5996
+ }
5997
+
5939
5998
// / Determine the default isolation and isolation source for this declaration,
5940
5999
// / which may still be overridden by other inference rules.
5941
6000
static std::tuple<InferredActorIsolation, ValueDecl *,
@@ -5955,24 +6014,34 @@ computeDefaultInferredActorIsolation(ValueDecl *value) {
5955
6014
auto *dc = value->getInnermostDeclContext ();
5956
6015
while (dc && !inActorContext) {
5957
6016
if (auto *nominal = dc->getSelfNominalTypeDecl ()) {
5958
- inActorContext = nominal->isAnyActor ();
6017
+ if (nominal->isAnyActor ())
6018
+ return {};
5959
6019
}
5960
6020
dc = dc->getParent ();
5961
6021
}
5962
6022
5963
- if (!inActorContext) {
5964
- // FIXME: deinit should be implicitly MainActor too.
5965
- if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
5966
- isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
5967
- isa<ConstructorDecl>(value)) {
6023
+ // If this is or is a non-type member of a nominal type that conforms to a
6024
+ // SendableMetatype-inheriting protocol in its primary definition, disable
6025
+ // @MainActor inference.
6026
+ auto nominalTypeDecl = dyn_cast<NominalTypeDecl>(value);
6027
+ if (!nominalTypeDecl && !isa<TypeDecl>(value)) {
6028
+ nominalTypeDecl = value->getDeclContext ()->getSelfNominalTypeDecl ();
6029
+ }
6030
+ if (nominalTypeDecl &&
6031
+ sendableConformanceRequiresNonisolated (nominalTypeDecl))
6032
+ return { };
6033
+
6034
+ // FIXME: deinit should be implicitly MainActor too.
6035
+ if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
6036
+ isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
6037
+ isa<ConstructorDecl>(value)) {
5968
6038
// Preconcurrency here is used to stage the diagnostics
5969
6039
// when users select `@MainActor` default isolation with
5970
6040
// non-strict concurrency modes (pre Swift 6).
5971
6041
auto isolation =
5972
6042
ActorIsolation::forGlobalActor (globalActor)
5973
6043
.withPreconcurrency (!ctx.LangOpts .isSwiftVersionAtLeast (6 ));
5974
6044
return {{{isolation, {}}, nullptr , {}}};
5975
- }
5976
6045
}
5977
6046
5978
6047
return {};
0 commit comments