@@ -7810,31 +7810,68 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
7810
7810
if (auto var = dyn_cast<VarDecl>(D)) {
7811
7811
// stored properties have limitations as to when they can be nonisolated.
7812
7812
auto type = var->getTypeInContext ();
7813
- if (var->hasStorage ()) {
7813
+ if (var->hasStorage () || var->hasAttachedPropertyWrapper () ||
7814
+ var->getAttrs ().hasAttribute <LazyAttr>()) {
7815
+
7816
+ if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) {
7817
+ // 'nonisolated' can not be applied to stored properties inside
7818
+ // distributed actors. Attempts of nonisolated access would be
7819
+ // cross-actor, which means they might be accessing on a remote actor,
7820
+ // in which case the stored property storage does not exist.
7821
+ //
7822
+ // The synthesized "id" and "actorSystem" are the only exceptions,
7823
+ // because the implementation mirrors them.
7824
+ if (nominal->isDistributedActor () &&
7825
+ !(var->getName () == Ctx.Id_id ||
7826
+ var->getName () == Ctx.Id_actorSystem )) {
7827
+ diagnoseAndRemoveAttr (attr,
7828
+ diag::nonisolated_distributed_actor_storage);
7829
+ return ;
7830
+ }
7831
+ }
7832
+
7814
7833
{
7815
7834
// A stored property can be 'nonisolated' if it is a 'Sendable' member
7816
7835
// of a 'Sendable' value type.
7836
+ // The above rule does not apply to lazy properties and properties with
7837
+ // property wrappers, because backing storage is a stored
7838
+ // 'var' that is part of the internal state of the actor which could
7839
+ // only be accessed in actor's isolation context.
7817
7840
bool canBeNonisolated = false ;
7818
7841
if (auto nominal = dc->getSelfStructDecl ()) {
7819
- if (nominal->getDeclaredTypeInContext ()->isSendableType () &&
7842
+ if (var->hasStorage () &&
7843
+ nominal->getDeclaredTypeInContext ()->isSendableType () &&
7820
7844
!var->isStatic () && type->isSendableType ()) {
7821
7845
canBeNonisolated = true ;
7822
7846
}
7823
7847
}
7824
7848
7825
- // Additionally, a stored property of a non-'Sendable' type can be
7826
- // explicitly marked 'nonisolated'.
7827
- if (auto parentDecl = dc->getDeclaredTypeInContext ())
7828
- if (!parentDecl->isSendableType ()) {
7829
- canBeNonisolated = true ;
7830
- }
7849
+ // Additionally, a stored property of a non-'Sendable' type can be
7850
+ // explicitly marked 'nonisolated'.
7851
+ if (auto parentDecl = dc->getDeclaredTypeInContext ())
7852
+ if (!parentDecl->isSendableType ()) {
7853
+ canBeNonisolated = true ;
7854
+ }
7831
7855
7832
7856
// Otherwise, this stored property has to be qualified as 'unsafe'.
7833
7857
if (var->supportsMutation () && !attr->isUnsafe () && !canBeNonisolated) {
7834
- diagnoseAndRemoveAttr (attr, diag::nonisolated_mutable_storage)
7858
+ if (var->hasAttachedPropertyWrapper ()) {
7859
+ diagnoseAndRemoveAttr (attr, diag::nonisolated_mutable_storage)
7860
+ .warnUntilSwiftVersionIf (attr->isImplicit (), 6 )
7835
7861
.fixItInsertAfter (attr->getRange ().End , " (unsafe)" );
7836
- var->diagnose (diag::nonisolated_mutable_storage_note, var);
7837
- return ;
7862
+ return ;
7863
+ } else if (var->getAttrs ().hasAttribute <LazyAttr>()) {
7864
+ diagnoseAndRemoveAttr (attr, diag::nonisolated_mutable_storage)
7865
+ .warnUntilSwiftVersion (6 )
7866
+ .fixItInsertAfter (attr->getRange ().End , " (unsafe)" );
7867
+ return ;
7868
+ } else {
7869
+ diagnoseAndRemoveAttr (attr, diag::nonisolated_mutable_storage)
7870
+ .fixItInsertAfter (attr->getRange ().End , " (unsafe)" );
7871
+ if (var->hasStorage ())
7872
+ var->diagnose (diag::nonisolated_mutable_storage_note, var);
7873
+ return ;
7874
+ }
7838
7875
}
7839
7876
7840
7877
// 'nonisolated' without '(unsafe)' is not allowed on non-Sendable
@@ -7848,23 +7885,6 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
7848
7885
}
7849
7886
}
7850
7887
7851
- if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) {
7852
- // 'nonisolated' can not be applied to stored properties inside
7853
- // distributed actors. Attempts of nonisolated access would be
7854
- // cross-actor, which means they might be accessing on a remote actor,
7855
- // in which case the stored property storage does not exist.
7856
- //
7857
- // The synthesized "id" and "actorSystem" are the only exceptions,
7858
- // because the implementation mirrors them.
7859
- if (nominal->isDistributedActor () &&
7860
- !(var->getName () == Ctx.Id_id ||
7861
- var->getName () == Ctx.Id_actorSystem )) {
7862
- diagnoseAndRemoveAttr (attr,
7863
- diag::nonisolated_distributed_actor_storage);
7864
- return ;
7865
- }
7866
- }
7867
-
7868
7888
// 'nonisolated(unsafe)' is redundant for 'Sendable' immutables.
7869
7889
if (attr->isUnsafe () &&
7870
7890
type->isSendableType () &&
@@ -7900,22 +7920,6 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
7900
7920
}
7901
7921
}
7902
7922
7903
- // Using 'nonisolated' with lazy properties and wrapped properties is
7904
- // unsupported, because backing storage is a stored 'var' that is part
7905
- // of the internal state of the actor which could only be accessed in
7906
- // actor's isolation context.
7907
- if (var->hasAttachedPropertyWrapper ()) {
7908
- diagnoseAndRemoveAttr (attr, diag::nonisolated_wrapped_property)
7909
- .warnUntilSwiftVersionIf (attr->isImplicit (), 6 );
7910
- return ;
7911
- }
7912
-
7913
- if (var->getAttrs ().hasAttribute <LazyAttr>()) {
7914
- diagnose (attr->getLocation (), diag::nonisolated_lazy)
7915
- .warnUntilSwiftVersion (6 );
7916
- return ;
7917
- }
7918
-
7919
7923
// nonisolated can not be applied to local properties unless qualified as
7920
7924
// 'unsafe'.
7921
7925
if (dc->isLocalContext () && !attr->isUnsafe ()) {
0 commit comments