Skip to content

Commit 982e14b

Browse files
committed
Stop inferring actor isolation from property wrappers in Swift 6.
In Swift 5, isolation will continue, but will now produce a warning and a fix-it suggesting that the user add explicit isolation
1 parent 0af3523 commit 982e14b

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5122,6 +5122,12 @@ ERROR(async_unavailable_decl,none,
51225122
"%0 %1 is unavailable from asynchronous contexts%select{|; %2}2",
51235123
(DescriptiveDeclKind, DeclBaseName, StringRef))
51245124

5125+
WARNING(actor_isolation_inferred_from_property_wrapper,none,
5126+
"%0 is implicitly %1 because it uses %2. This implicit isolation "
5127+
"will no longer happen in Swift 6.",
5128+
(DeclName, ActorIsolation, StringRef))
5129+
5130+
51255131
//------------------------------------------------------------------------------
51265132
// MARK: String Processing
51275133
//------------------------------------------------------------------------------

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3449,8 +3449,16 @@ static Optional<ActorIsolation> getIsolationFromWrappers(
34493449

34503450
if (!nominal->getParentSourceFile())
34513451
return None;
3452-
3453-
Optional<ActorIsolation> foundIsolation;
3452+
3453+
ASTContext &ctx = nominal->getASTContext();
3454+
if (ctx.isSwiftVersionAtLeast(6)) {
3455+
// In Swift 6, we no longer infer isolation of a nominal type based
3456+
// on property wrappers used in its stored properties
3457+
return None;
3458+
}
3459+
3460+
Optional<std::pair<ActorIsolation, Type>> foundIsolationAndType;
3461+
34543462
for (auto member : nominal->getMembers()) {
34553463
auto var = dyn_cast<VarDecl>(member);
34563464
if (!var || !var->isInstanceMember())
@@ -3475,19 +3483,36 @@ static Optional<ActorIsolation> getIsolationFromWrappers(
34753483

34763484
case ActorIsolation::GlobalActor:
34773485
case ActorIsolation::GlobalActorUnsafe:
3478-
if (!foundIsolation) {
3479-
foundIsolation = isolation;
3480-
continue;
3486+
if (!foundIsolationAndType) {
3487+
if (auto propertyWrapperType = var->getAttachedPropertyWrapperType(0)) {
3488+
foundIsolationAndType = { isolation, propertyWrapperType };
3489+
continue;
3490+
}
34813491
}
34823492

3483-
if (*foundIsolation != isolation)
3493+
if (foundIsolationAndType->first != isolation)
34843494
return None;
34853495

34863496
break;
34873497
}
34883498
}
34893499

3490-
return foundIsolation;
3500+
if (foundIsolationAndType) {
3501+
// We are inferring isolation for the type because
3502+
// it contains an actor-isolated property wrapper.
3503+
// Warn that this inferrence will be going away in
3504+
// Swift 6
3505+
const ActorIsolation isolation = foundIsolationAndType->first;
3506+
const Type type = foundIsolationAndType->second;
3507+
3508+
nominal->diagnose(diag::actor_isolation_inferred_from_property_wrapper,
3509+
nominal->getName(), isolation, "'@"+type->getString()+"'")
3510+
.fixItInsert(nominal->getAttributeInsertionLoc(false), "@" + isolation.getGlobalActor().getString());
3511+
return isolation;
3512+
}
3513+
else {
3514+
return None;
3515+
}
34913516
}
34923517

34933518
namespace {
@@ -4063,8 +4088,8 @@ ActorIsolation ActorIsolationRequest::evaluate(
40634088
if (auto inferred = inferredIsolation(*conformanceIsolation))
40644089
return inferred;
40654090

4066-
// If the declaration is a nominal type and any property wrappers on
4067-
// its stored properties require isolation, use that.
4091+
// Before Swift 6: If the declaration is a nominal type and any property
4092+
// wrappers on its stored properties require isolation, use that.
40684093
if (auto wrapperIsolation = getIsolationFromWrappers(nominal)) {
40694094
if (auto inferred = inferredIsolation(*wrapperIsolation))
40704095
return inferred;

0 commit comments

Comments
 (0)