@@ -7810,31 +7810,68 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
78107810 if (auto var = dyn_cast<VarDecl>(D)) {
78117811 // stored properties have limitations as to when they can be nonisolated.
78127812 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+
78147833 {
78157834 // A stored property can be 'nonisolated' if it is a 'Sendable' member
78167835 // 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.
78177840 bool canBeNonisolated = false ;
78187841 if (auto nominal = dc->getSelfStructDecl ()) {
7819- if (nominal->getDeclaredTypeInContext ()->isSendableType () &&
7842+ if (var->hasStorage () &&
7843+ nominal->getDeclaredTypeInContext ()->isSendableType () &&
78207844 !var->isStatic () && type->isSendableType ()) {
78217845 canBeNonisolated = true ;
78227846 }
78237847 }
78247848
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+ }
78317855
78327856 // Otherwise, this stored property has to be qualified as 'unsafe'.
78337857 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 )
78357861 .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+ }
78387875 }
78397876
78407877 // 'nonisolated' without '(unsafe)' is not allowed on non-Sendable
@@ -7848,23 +7885,6 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
78487885 }
78497886 }
78507887
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-
78687888 // 'nonisolated(unsafe)' is redundant for 'Sendable' immutables.
78697889 if (attr->isUnsafe () &&
78707890 type->isSendableType () &&
@@ -7900,22 +7920,6 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
79007920 }
79017921 }
79027922
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-
79197923 // nonisolated can not be applied to local properties unless qualified as
79207924 // 'unsafe'.
79217925 if (dc->isLocalContext () && !attr->isUnsafe ()) {
0 commit comments