@@ -5282,6 +5282,33 @@ getIsolationFromAttributes(const Decl *decl, bool shouldDiagnose = true,
5282
5282
llvm_unreachable (" Forgot about an attribute?" );
5283
5283
}
5284
5284
5285
+ // / Determine the default isolation for the given declaration context.
5286
+ static DefaultIsolation getDefaultIsolationForContext (const DeclContext *dc) {
5287
+ // Check whether there is a file-specific setting.
5288
+ if (auto *sourceFile = dc->getParentSourceFile ()) {
5289
+ if (auto defaultIsolationInFile = sourceFile->getDefaultIsolation ())
5290
+ return defaultIsolationInFile.value ();
5291
+ }
5292
+
5293
+ // If we're in the main module, check the language option.
5294
+ ASTContext &ctx = dc->getASTContext ();
5295
+ if (dc->getParentModule () == ctx.MainModule )
5296
+ return ctx.LangOpts .DefaultIsolationBehavior ;
5297
+
5298
+ // Otherwise, default to nonisolated.
5299
+ return DefaultIsolation::Nonisolated;
5300
+ }
5301
+
5302
+ // / Determines whether explicit 'nonisolated' is different from 'unspecified'
5303
+ // / in the given context.
5304
+ static bool explicitNonisolatedIsSpecial (const DeclContext *dc) {
5305
+ ASTContext &ctx = dc->getASTContext ();
5306
+ if (ctx.LangOpts .hasFeature (Feature::NoExplicitNonIsolated))
5307
+ return false ;
5308
+
5309
+ return getDefaultIsolationForContext (dc) == DefaultIsolation::Nonisolated;
5310
+ }
5311
+
5285
5312
// / Infer isolation from witnessed protocol requirements.
5286
5313
static std::optional<InferredActorIsolation>
5287
5314
getIsolationFromWitnessedRequirements (ValueDecl *value) {
@@ -5298,11 +5325,13 @@ getIsolationFromWitnessedRequirements(ValueDecl *value) {
5298
5325
if (dc->getSelfProtocolDecl ())
5299
5326
return std::nullopt;
5300
5327
5301
- // Prevent isolation inference from requirements if the conforming type
5302
- // has an explicit `nonisolated` attribute.
5303
- if (auto *NTD = dc->getSelfNominalTypeDecl ()) {
5304
- if (NTD->getAttrs ().hasAttribute <NonisolatedAttr>())
5305
- return std::nullopt;
5328
+ if (explicitNonisolatedIsSpecial (dc)) {
5329
+ // Prevent isolation inference from requirements if the conforming type
5330
+ // has an explicit `nonisolated` attribute.
5331
+ if (auto *NTD = dc->getSelfNominalTypeDecl ()) {
5332
+ if (NTD->getAttrs ().hasAttribute <NonisolatedAttr>())
5333
+ return std::nullopt;
5334
+ }
5306
5335
}
5307
5336
5308
5337
// Walk through each of the conformances in this context, collecting any
@@ -5360,8 +5389,13 @@ getIsolationFromWitnessedRequirements(ValueDecl *value) {
5360
5389
}
5361
5390
5362
5391
case ActorIsolation::GlobalActor:
5392
+ break ;
5393
+
5363
5394
case ActorIsolation::Nonisolated:
5364
5395
case ActorIsolation::NonisolatedUnsafe:
5396
+ if (!explicitNonisolatedIsSpecial (requirement->getDeclContext ()))
5397
+ continue ;
5398
+
5365
5399
break ;
5366
5400
}
5367
5401
@@ -5468,7 +5502,8 @@ getIsolationFromConformances(NominalTypeDecl *nominal) {
5468
5502
case ActorIsolation::NonisolatedUnsafe:
5469
5503
break ;
5470
5504
case ActorIsolation::Nonisolated:
5471
- if (inferredIsolation.source .kind == IsolationSource::Kind::Explicit) {
5505
+ if (inferredIsolation.source .kind == IsolationSource::Kind::Explicit &&
5506
+ explicitNonisolatedIsSpecial (nominal)) {
5472
5507
if (!foundIsolation) {
5473
5508
// We found an explicitly 'nonisolated' protocol.
5474
5509
foundIsolation = {
@@ -6131,12 +6166,27 @@ computeDefaultInferredActorIsolation(ValueDecl *value) {
6131
6166
return {};
6132
6167
6133
6168
if (dc != dyn_cast<DeclContext>(value)) {
6169
+ // If the nominal type is global-actor-isolated, there's nothing
6170
+ // more to look for.
6134
6171
if (getActorIsolation (nominal).isMainActor ())
6135
6172
break ;
6136
6173
6137
- return {};
6174
+ // If this is an extension of a nonisolated type, its isolation
6175
+ // is independent of the type.
6176
+ if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
6177
+ // If there were isolation attributes on the extension, respect
6178
+ // them.
6179
+ if (getIsolationFromAttributes (ext).has_value ())
6180
+ return {};
6181
+
6182
+ // Keep looking.
6183
+ } else {
6184
+ // The type is nonisolated, so its members are nonisolated.
6185
+ return {};
6186
+ }
6138
6187
}
6139
6188
}
6189
+
6140
6190
dc = dc->getParent ();
6141
6191
}
6142
6192
@@ -6166,12 +6216,8 @@ computeDefaultInferredActorIsolation(ValueDecl *value) {
6166
6216
return {};
6167
6217
};
6168
6218
6169
- DefaultIsolation defaultIsolation = ctx.LangOpts .DefaultIsolationBehavior ;
6170
- if (auto *SF = value->getDeclContext ()->getParentSourceFile ()) {
6171
- if (auto defaultIsolationInFile = SF->getDefaultIsolation ())
6172
- defaultIsolation = defaultIsolationInFile.value ();
6173
- }
6174
-
6219
+ DefaultIsolation defaultIsolation =
6220
+ getDefaultIsolationForContext (value->getDeclContext ());
6175
6221
// If we are required to use main actor... just use that.
6176
6222
if (defaultIsolation == DefaultIsolation::MainActor)
6177
6223
if (auto result =
@@ -6248,6 +6294,36 @@ computeDefaultInferredActorIsolation(ValueDecl *value) {
6248
6294
return {{ActorIsolation::forUnspecified (), {}}, nullptr , {}};
6249
6295
}
6250
6296
6297
+ // / Determines when the given "self" isolation should override default
6298
+ // / isolation.
6299
+ static bool shouldSelfIsolationOverrideDefault (
6300
+ ASTContext &ctx, const DeclContext *dc,
6301
+ const ActorIsolation &selfIsolation) {
6302
+ switch (selfIsolation) {
6303
+ case ActorIsolation::ActorInstance:
6304
+ case ActorIsolation::Erased:
6305
+ case ActorIsolation::GlobalActor:
6306
+ // Actor isolation always overrides.
6307
+ return true ;
6308
+
6309
+ case ActorIsolation::Unspecified:
6310
+ // Unspecified isolation never overrides.
6311
+ return false ;
6312
+
6313
+ case ActorIsolation::Nonisolated:
6314
+ case ActorIsolation::NonisolatedUnsafe:
6315
+ case ActorIsolation::CallerIsolationInheriting:
6316
+ // Explicit nonisolated used to overwrite default isolation all the time,
6317
+ // but under NoExplicitNonIsolated it doesn't affect extensions.
6318
+ if (isa<NominalTypeDecl>(dc))
6319
+ return true ;
6320
+
6321
+ // / Only allow explicit nonisolated to override the default when it's
6322
+ // / treated as special.
6323
+ return explicitNonisolatedIsSpecial (dc);
6324
+ }
6325
+ }
6326
+
6251
6327
static InferredActorIsolation computeActorIsolation (Evaluator &evaluator,
6252
6328
ValueDecl *value) {
6253
6329
// If this declaration has actor-isolated "self", it's isolated to that
@@ -6580,7 +6656,8 @@ static InferredActorIsolation computeActorIsolation(Evaluator &evaluator,
6580
6656
// has isolation, use that.
6581
6657
if (auto selfTypeDecl = value->getDeclContext ()->getSelfNominalTypeDecl ()) {
6582
6658
auto selfTypeIsolation = getInferredActorIsolation (selfTypeDecl);
6583
- if (selfTypeIsolation.isolation ) {
6659
+ if (shouldSelfIsolationOverrideDefault (
6660
+ ctx, value->getDeclContext (), selfTypeIsolation.isolation )) {
6584
6661
auto isolation = selfTypeIsolation.isolation ;
6585
6662
6586
6663
if (ctx.LangOpts .hasFeature (Feature::NonisolatedNonsendingByDefault) &&
@@ -8426,6 +8503,19 @@ ActorIsolation swift::inferConformanceIsolation(
8426
8503
// isolated to a global actor, we may use the conforming type's isolation.
8427
8504
auto nominalIsolation = getActorIsolation (nominal);
8428
8505
if (!nominalIsolation.isGlobalActor ()) {
8506
+ // If we are in an extension of the type, we might still infer an
8507
+ // isolated conformance depending on default isolation and on the extension
8508
+ // itself.
8509
+ if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
8510
+ // If there's an isolation-related attribute on the extension, use it.
8511
+ if (auto attrIsolation = getIsolationFromAttributes (ext))
8512
+ return *attrIsolation;
8513
+
8514
+ // If we're defaulting to main-actor isolation, use that.
8515
+ if (getDefaultIsolationForContext (dc) == DefaultIsolation::MainActor)
8516
+ return ActorIsolation::forMainActor (ctx);
8517
+ }
8518
+
8429
8519
return ActorIsolation::forNonisolated (false );
8430
8520
}
8431
8521
0 commit comments