Skip to content

Commit f56ba59

Browse files
committed
Add 'nonisolated' modifier as the preferred spelling for @actorIndependent
1 parent 75a9f4f commit f56ba59

File tree

9 files changed

+103
-29
lines changed

9 files changed

+103
-29
lines changed

include/swift/AST/Attr.def

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ SIMPLE_DECL_ATTR(reasync, Reasync,
620620
109)
621621

622622
SIMPLE_DECL_ATTR(reasync, AtReasync,
623-
OnProtocol |
623+
OnProtocol | ConcurrencyOnly |
624624
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
625625
110)
626626

@@ -630,6 +630,13 @@ DECL_ATTR(hasAsyncAlternative, HasAsyncAlternative,
630630
APIStableToAdd | APIStableToRemove,
631631
111)
632632

633+
CONTEXTUAL_SIMPLE_DECL_ATTR(nonisolated, Nonisolated,
634+
OnFunc | OnConstructor | OnVar | OnSubscript | ConcurrencyOnly |
635+
ABIStableToAdd | ABIStableToRemove |
636+
APIBreakingToAdd | APIStableToRemove,
637+
112)
638+
639+
633640
#undef TYPE_ATTR
634641
#undef DECL_ATTR_ALIAS
635642
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsSema.def

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4212,8 +4212,8 @@ NOTE(note_add_async_to_function,none,
42124212
"add 'async' to function %0 to make it asynchronous", (DeclName))
42134213
NOTE(note_add_asynchandler_to_function,none,
42144214
"add '@asyncHandler' to function %0 to create an implicit asynchronous context", (DeclName))
4215-
NOTE(note_add_actorindependent_to_decl,none,
4216-
"add '@actorIndependent' to %0 to make this %1 independent of the actor",
4215+
NOTE(note_add_nonisolated_to_decl,none,
4216+
"add 'nonisolated' to %0 to make this %1 not isolated to the actor",
42174217
(DeclName, DescriptiveDeclKind))
42184218
NOTE(note_add_globalactor_to_function,none,
42194219
"add '@%0' to make %1 %2 part of global actor %3",
@@ -4407,9 +4407,20 @@ ERROR(actorindependent_local_var,none,
44074407
"'@actorIndependent' can not be applied to local variables",
44084408
())
44094409

4410+
ERROR(nonisolated_let,none,
4411+
"'nonisolated' is meaningless on 'let' declarations because "
4412+
"they are immutable",
4413+
())
4414+
ERROR(nonisolated_mutable_storage,none,
4415+
"nonisolated' can not be applied to stored properties",
4416+
())
4417+
ERROR(nonisolated_local_var,none,
4418+
"'nonisolated' can not be applied to local variables",
4419+
())
4420+
44104421
ERROR(actor_instance_property_wrapper,none,
44114422
"%0 property in property wrapper type %1 cannot be isolated to "
4412-
"the actor instance; consider @actorIndependent",
4423+
"the actor instance; consider 'nonisolated'",
44134424
(Identifier, Identifier))
44144425

44154426
ERROR(concurrency_lib_missing,none,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
281281
void visitMarkerAttr(MarkerAttr *attr);
282282

283283
void visitReasyncAttr(ReasyncAttr *attr);
284+
void visitNonisolatedAttr(NonisolatedAttr *attr);
284285
};
285286
} // end anonymous namespace
286287

@@ -5476,6 +5477,41 @@ void AttributeChecker::visitActorIndependentAttr(ActorIndependentAttr *attr) {
54765477
}
54775478
}
54785479

5480+
void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
5481+
// 'nonisolated' can be applied to global and static/class variables
5482+
// that do not have storage.
5483+
auto dc = D->getDeclContext();
5484+
if (auto var = dyn_cast<VarDecl>(D)) {
5485+
// 'nonisolated' is meaningless on a `let`.
5486+
if (var->isLet()) {
5487+
diagnoseAndRemoveAttr(attr, diag::nonisolated_let);
5488+
return;
5489+
}
5490+
5491+
// 'nonisolated' can not be applied to stored properties.
5492+
if (var->hasStorage()) {
5493+
diagnoseAndRemoveAttr(attr, diag::nonisolated_mutable_storage);
5494+
return;
5495+
}
5496+
5497+
// @actorIndependent can not be applied to local properties.
5498+
if (dc->isLocalContext()) {
5499+
diagnoseAndRemoveAttr(attr, diag::nonisolated_local_var);
5500+
return;
5501+
}
5502+
5503+
// If this is a static or global variable, we're all set.
5504+
if (dc->isModuleScopeContext() ||
5505+
(dc->isTypeContext() && var->isStatic())) {
5506+
return;
5507+
}
5508+
}
5509+
5510+
if (auto VD = dyn_cast<ValueDecl>(D)) {
5511+
(void)getActorIsolation(VD);
5512+
}
5513+
}
5514+
54795515
void AttributeChecker::visitGlobalActorAttr(GlobalActorAttr *attr) {
54805516
auto nominal = dyn_cast<NominalTypeDecl>(D);
54815517
if (!nominal)

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,13 +2241,16 @@ static Optional<ActorIsolation> getIsolationFromAttributes(
22412241
// Look up attributes on the declaration that can affect its actor isolation.
22422242
// If any of them are present, use that attribute.
22432243
auto independentAttr = decl->getAttrs().getAttribute<ActorIndependentAttr>();
2244+
auto nonisolatedAttr = decl->getAttrs().getAttribute<NonisolatedAttr>();
22442245
auto globalActorAttr = decl->getGlobalActorAttr();
22452246
unsigned numIsolationAttrs =
2246-
(independentAttr ? 1 : 0) + (globalActorAttr ? 1 : 0);
2247+
(nonisolatedAttr ? 1 : 0) + (independentAttr ? 1 : 0) +
2248+
(globalActorAttr ? 1 : 0);
22472249
if (numIsolationAttrs == 0)
22482250
return None;
22492251

2250-
// Only one such attribute is valid.
2252+
// Only one such attribute is valid, but we only actually care of one of
2253+
// them is a global actor.
22512254
if (numIsolationAttrs > 1) {
22522255
DeclName name;
22532256
if (auto value = dyn_cast<ValueDecl>(decl)) {
@@ -2257,16 +2260,34 @@ static Optional<ActorIsolation> getIsolationFromAttributes(
22572260
name = selfTypeDecl->getName();
22582261
}
22592262

2260-
if (shouldDiagnose) {
2261-
decl->diagnose(
2262-
diag::actor_isolation_multiple_attr, decl->getDescriptiveKind(),
2263-
name, independentAttr->getAttrName(),
2264-
globalActorAttr->second->getName().str())
2265-
.highlight(independentAttr->getRangeWithAt())
2266-
.highlight(globalActorAttr->first->getRangeWithAt());
2263+
if (globalActorAttr) {
2264+
StringRef nonisolatedAttrName;
2265+
SourceRange nonisolatedRange;
2266+
if (independentAttr) {
2267+
nonisolatedAttrName = independentAttr->getAttrName();
2268+
nonisolatedRange = independentAttr->getRangeWithAt();
2269+
} else {
2270+
nonisolatedAttrName = nonisolatedAttr->getAttrName();
2271+
nonisolatedRange = nonisolatedAttr->getRangeWithAt();
2272+
}
2273+
2274+
if (shouldDiagnose) {
2275+
decl->diagnose(
2276+
diag::actor_isolation_multiple_attr, decl->getDescriptiveKind(),
2277+
name, nonisolatedAttrName,
2278+
globalActorAttr->second->getName().str())
2279+
.highlight(nonisolatedRange)
2280+
.highlight(globalActorAttr->first->getRangeWithAt());
2281+
}
22672282
}
22682283
}
22692284

2285+
// If the declaration is explicitly marked 'nonisolated', report it as
2286+
// independent.
2287+
if (nonisolatedAttr) {
2288+
return ActorIsolation::forIndependent(ActorIndependentKind::Safe);
2289+
}
2290+
22702291
// If the declaration is explicitly marked @actorIndependent, report it as
22712292
// independent.
22722293
if (independentAttr) {

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,7 @@ namespace {
15401540
UNINTERESTING_ATTR(Marker)
15411541

15421542
UNINTERESTING_ATTR(AtReasync)
1543+
UNINTERESTING_ATTR(Nonisolated)
15431544

15441545
#undef UNINTERESTING_ATTR
15451546

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2748,10 +2748,10 @@ bool ConformanceChecker::checkActorIsolation(
27482748
auto witnessVar = dyn_cast<VarDecl>(witness);
27492749
if ((witnessVar && !witnessVar->hasStorage()) || !witnessVar) {
27502750
auto independentNote = witness->diagnose(
2751-
diag::note_add_actorindependent_to_decl,
2751+
diag::note_add_nonisolated_to_decl,
27522752
witness->getName(), witness->getDescriptiveKind());
2753-
independentNote.fixItInsert(witness->getAttributeInsertionLoc(false),
2754-
"@actorIndependent ");
2753+
independentNote.fixItInsert(witness->getAttributeInsertionLoc(true),
2754+
"nonisolated ");
27552755
}
27562756
}
27572757

test/Concurrency/global_actor_inference.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ func barSync() {
243243
struct WrapperOnActor<Wrapped> {
244244
@actorIndependent(unsafe) private var stored: Wrapped
245245

246-
@actorIndependent init(wrappedValue: Wrapped) {
246+
nonisolated init(wrappedValue: Wrapped) {
247247
stored = wrappedValue
248248
}
249249

@@ -266,12 +266,12 @@ actor WrapperActor<Wrapped> {
266266
storage = wrappedValue
267267
}
268268

269-
@actorIndependent var wrappedValue: Wrapped {
269+
nonisolated var wrappedValue: Wrapped {
270270
get { storage }
271271
set { storage = newValue }
272272
}
273273

274-
@actorIndependent var projectedValue: Wrapped {
274+
nonisolated var projectedValue: Wrapped {
275275
get { storage }
276276
set { storage = newValue }
277277
}
@@ -311,7 +311,7 @@ actor WrapperActorBad1<Wrapped> {
311311
storage = wrappedValue
312312
}
313313

314-
var wrappedValue: Wrapped { // expected-error{{'wrappedValue' property in property wrapper type 'WrapperActorBad1' cannot be isolated to the actor instance; consider @actorIndependent}}}}
314+
var wrappedValue: Wrapped { // expected-error{{'wrappedValue' property in property wrapper type 'WrapperActorBad1' cannot be isolated to the actor instance; consider 'nonisolated'}}}}
315315
get { storage }
316316
set { storage = newValue }
317317
}
@@ -325,12 +325,12 @@ actor WrapperActorBad2<Wrapped> {
325325
storage = wrappedValue
326326
}
327327

328-
@actorIndependent var wrappedValue: Wrapped {
328+
nonisolated var wrappedValue: Wrapped {
329329
get { storage }
330330
set { storage = newValue }
331331
}
332332

333-
var projectedValue: Wrapped { // expected-error{{'projectedValue' property in property wrapper type 'WrapperActorBad2' cannot be isolated to the actor instance; consider @actorIndependent}}
333+
var projectedValue: Wrapped { // expected-error{{'projectedValue' property in property wrapper type 'WrapperActorBad2' cannot be isolated to the actor instance; consider 'nonisolated'}}
334334
get { storage }
335335
set { storage = newValue }
336336
}
@@ -358,7 +358,7 @@ struct StructUGA1: UGA {
358358
}
359359

360360
struct StructUGA2: UGA {
361-
@actorIndependent func req() { }
361+
nonisolated func req() { }
362362
}
363363

364364
@GenericGlobalActor<String>
@@ -408,7 +408,7 @@ struct HasWrapperOnUnsafeActor {
408408
_ = _synced
409409
}
410410

411-
@actorIndependent func testErrors() {
411+
nonisolated func testErrors() {
412412
_ = synced // expected-error{{property 'synced' isolated to global actor 'MainActor' can not be referenced from}}
413413
_ = $synced // expected-error{{property '$synced' isolated to global actor 'SomeGlobalActor' can not be referenced from}}
414414
_ = _synced // expected-error{{property '_synced' isolated to global actor 'OtherGlobalActor' can not be referenced from}}

test/IDE/complete_decl_attribute.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ struct _S {
242242
// ON_MEMBER_LAST-DAG: Keyword/None: objcMembers[#Declaration Attribute#]; name=objcMembers
243243
// ON_MEMBER_LAST-DAG: Keyword/None: NSApplicationMain[#Declaration Attribute#]; name=NSApplicationMain
244244
// ON_MEMBER_LAST-DAG: Keyword/None: rethrows[#Declaration Attribute#]; name=rethrows
245-
// ON_MEMBER_LAST-DAG: Keyword/None: reasync[#Declaration Attribute#]; name=reasync
246245
// ON_MEMBER_LAST-DAG: Keyword/None: warn_unqualified_access[#Declaration Attribute#]; name=warn_unqualified_access
247246
// ON_MEMBER_LAST-DAG: Keyword/None: usableFromInline[#Declaration Attribute#]; name=usableFromInline
248247
// ON_MEMBER_LAST-DAG: Keyword/None: discardableResult[#Declaration Attribute#]; name=discardableResult
@@ -291,7 +290,6 @@ func dummy2() {}
291290
// KEYWORD_LAST-DAG: Keyword/None: inlinable[#Declaration Attribute#]; name=inlinable{{$}}
292291
// KEYWORD_LAST-DAG: Keyword/None: objcMembers[#Declaration Attribute#]; name=objcMembers{{$}}
293292
// KEYWORD_LAST-DAG: Keyword/None: NSApplicationMain[#Declaration Attribute#]; name=NSApplicationMain{{$}}
294-
// KEYWORD_LAST-DAG: Keyword/None: reasync[#Declaration Attribute#]; name=reasync{{$}}
295293
// KEYWORD_LAST-DAG: Keyword/None: rethrows[#Declaration Attribute#]; name=rethrows{{$}}
296294
// KEYWORD_LAST-DAG: Keyword/None: warn_unqualified_access[#Declaration Attribute#]; name=warn_unqualified_access
297295
// KEYWORD_LAST-DAG: Keyword/None: usableFromInline[#Declaration Attribute#]; name=usableFromInline{{$}}

test/decl/class/actor/conformance.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ actor OtherActor: SyncProtocol {
3737

3838
var propertyA: Int { 17 }
3939
// expected-error@-1{{actor-isolated property 'propertyA' cannot be used to satisfy a protocol requirement}}
40-
// expected-note@-2{{add '@actorIndependent' to 'propertyA' to make this property independent of the actor}}{{3-3=@actorIndependent }}
40+
// expected-note@-2{{add 'nonisolated' to 'propertyA' to make this property not isolated to the actor}}{{3-3=nonisolated }}
4141

4242
func syncMethodA() { }
4343
// expected-error@-1{{actor-isolated instance method 'syncMethodA()' cannot be used to satisfy a protocol requirement}}
44-
// expected-note@-2{{add '@actorIndependent' to 'syncMethodA()' to make this instance method independent of the actor}}{{3-3=@actorIndependent }}
44+
// expected-note@-2{{add 'nonisolated' to 'syncMethodA()' to make this instance method not isolated to the actor}}{{3-3=nonisolated }}
4545
// expected-note@-3{{add '@asyncHandler' to function 'syncMethodA()' to create an implicit asynchronous context}}{{3-3=@asyncHandler }}
4646

4747
// Async handlers are okay.
@@ -54,7 +54,7 @@ actor OtherActor: SyncProtocol {
5454

5555
subscript (index: Int) -> String { "\(index)" }
5656
// expected-error@-1{{actor-isolated subscript 'subscript(_:)' cannot be used to satisfy a protocol requirement}}
57-
// expected-note@-2{{add '@actorIndependent' to 'subscript(_:)' to make this subscript independent of the actor}}{{3-3=@actorIndependent }}
57+
// expected-note@-2{{add 'nonisolated' to 'subscript(_:)' to make this subscript not isolated to the actor}}{{3-3=nonisolated }}
5858

5959
// Static methods and properties are okay.
6060
static func staticMethod() { }

0 commit comments

Comments
 (0)