Skip to content

Commit 87c6867

Browse files
authored
Merge pull request swiftlang#35865 from DougGregor/initializer-actor-isolation
2 parents bdfd4a8 + 923ccfd commit 87c6867

File tree

4 files changed

+70
-12
lines changed

4 files changed

+70
-12
lines changed

lib/AST/Decl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6986,7 +6986,7 @@ AbstractFunctionDecl::getObjCSelector(DeclName preferredName,
69866986
}
69876987

69886988
// For the first selector piece, attach either the first parameter,
6989-
// "withCompletionHandker", or "AndReturnError" to the base name,
6989+
// "withCompletionHandler", or "AndReturnError" to the base name,
69906990
// if appropriate.
69916991
auto firstPiece = baseName;
69926992
llvm::SmallString<32> scratch;
@@ -7999,7 +7999,8 @@ ActorIsolation swift::getActorIsolationOfContext(DeclContext *dc) {
79997999
return getActorIsolation(vd);
80008000

80018001
if (auto *init = dyn_cast<PatternBindingInitializer>(dc)) {
8002-
if (auto *var = init->getBinding()->getSingleVar())
8002+
if (auto *var = init->getBinding()->getAnchoringVarDecl(
8003+
init->getBindingIndex()))
80038004
return getActorIsolation(var);
80048005
}
80058006

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -491,11 +491,9 @@ ActorIsolationRestriction ActorIsolationRestriction::forDeclaration(
491491
// Types are always available.
492492
return forUnrestricted();
493493

494-
case DeclKind::Constructor:
495494
case DeclKind::EnumCase:
496495
case DeclKind::EnumElement:
497496
// Type-level entities don't require isolation.
498-
// FIXME: This is incorrect due to global actors.
499497
return forUnrestricted();
500498

501499
case DeclKind::IfConfig:
@@ -519,6 +517,7 @@ ActorIsolationRestriction ActorIsolationRestriction::forDeclaration(
519517
case DeclKind::Param:
520518
case DeclKind::Var:
521519
case DeclKind::Accessor:
520+
case DeclKind::Constructor:
522521
case DeclKind::Func:
523522
case DeclKind::Subscript: {
524523
// Local captures can only be referenced in their local context or a
@@ -551,7 +550,8 @@ ActorIsolationRestriction ActorIsolationRestriction::forDeclaration(
551550
switch (auto isolation = getActorIsolation(cast<ValueDecl>(decl))) {
552551
case ActorIsolation::ActorInstance:
553552
// Protected actor instance members can only be accessed on 'self'.
554-
return forActorSelf(isolation.getActor(), isAccessibleAcrossActors);
553+
return forActorSelf(isolation.getActor(),
554+
isAccessibleAcrossActors || isa<ConstructorDecl>(decl));
555555

556556
case ActorIsolation::GlobalActor: {
557557
Type actorType = isolation.getGlobalActor();
@@ -2275,10 +2275,11 @@ ActorIsolation ActorIsolationRequest::evaluate(
22752275
}
22762276
}
22772277

2278-
// Check for instance members of actor classes, which are part of
2279-
// actor-isolated state.
2278+
// Check for instance members and initializers of actor classes,
2279+
// which are part of actor-isolated state.
22802280
auto classDecl = value->getDeclContext()->getSelfClassDecl();
2281-
if (classDecl && classDecl->isActor() && value->isInstanceMember()) {
2281+
if (classDecl && classDecl->isActor() &&
2282+
(value->isInstanceMember() || isa<ConstructorDecl>(value))) {
22822283
defaultIsolation = ActorIsolation::forActorInstance(classDecl);
22832284
}
22842285

@@ -2366,8 +2367,8 @@ ActorIsolation ActorIsolationRequest::evaluate(
23662367
}
23672368
}
23682369

2369-
// Instance members can infer isolation from their context.
2370-
if (value->isInstanceMember()) {
2370+
// Instance members and initializers can infer isolation from their context.
2371+
if (value->isInstanceMember() || isa<ConstructorDecl>(value)) {
23712372
// If the declaration is in an extension that has one of the isolation
23722373
// attributes, use that.
23732374
if (auto ext = dyn_cast<ExtensionDecl>(value->getDeclContext())) {

test/Concurrency/actor_isolation.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,3 +446,35 @@ extension SomeClassInActor.ID {
446446
object.inActor() // expected-error{{'async' in a function that does not support concurrency}}
447447
}
448448
}
449+
450+
// ----------------------------------------------------------------------
451+
// Initializers
452+
// ----------------------------------------------------------------------
453+
actor class SomeActorWithInits {
454+
var mutableState: Int = 17
455+
var otherMutableState: Int
456+
457+
init() {
458+
self.mutableState = 42
459+
self.otherMutableState = 17
460+
461+
self.isolated()
462+
}
463+
464+
func isolated() { }
465+
}
466+
467+
@MainActor
468+
class SomeClassWithInits {
469+
var mutableState: Int = 17
470+
var otherMutableState: Int
471+
472+
init() {
473+
self.mutableState = 42
474+
self.otherMutableState = 17
475+
476+
self.isolated()
477+
}
478+
479+
func isolated() { }
480+
}

test/Concurrency/concurrent_value_checking.swift

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ actor class A1 {
1313
func asynchronous(_: NotConcurrent?) async { }
1414
}
1515

16+
actor class A2 {
17+
var localVar: NotConcurrent
18+
19+
init(value: NotConcurrent) {
20+
self.localVar = value
21+
}
22+
}
23+
24+
func testActorCreation(value: NotConcurrent) {
25+
_ = A2(value: value) // expected-warning{{cannot pass argument of non-concurrent-value type 'NotConcurrent' across actors}}
26+
}
27+
1628
extension A1 {
1729
func testIsolation(other: A1) async {
1830
// All within the same actor domain, so the ConcurrentValue restriction
@@ -65,17 +77,29 @@ struct HasSubscript {
6577
subscript (i: Int) -> NotConcurrent? { nil }
6678
}
6779

80+
class ClassWithGlobalActorInits {
81+
@SomeGlobalActor
82+
init(_: NotConcurrent) { }
83+
84+
@SomeGlobalActor
85+
init() { }
86+
}
87+
88+
6889
@MainActor
69-
func globalTestMain() async {
90+
func globalTestMain(nc: NotConcurrent) async {
7091
let a = globalValue // expected-warning{{cannot use let 'globalValue' with a non-concurrent-value type 'NotConcurrent?' across actors}}
7192
await globalAsync(a) // expected-warning{{cannot pass argument of non-concurrent-value type 'NotConcurrent?' across actors}}
7293
await globalSync(a) // expected-warning{{cannot pass argument of non-concurrent-value type 'NotConcurrent?' across actors}}
94+
_ = await ClassWithGlobalActorInits(nc) // expected-warning{{cannot pass argument of non-concurrent-value type 'NotConcurrent' across actors}}
95+
_ = await ClassWithGlobalActorInits()
7396
}
7497

7598
@SomeGlobalActor
76-
func someGlobalTest() {
99+
func someGlobalTest(nc: NotConcurrent) {
77100
let hs = HasSubscript()
78101
let _ = hs[0] // okay
102+
_ = ClassWithGlobalActorInits(nc)
79103
}
80104

81105
// ----------------------------------------------------------------------

0 commit comments

Comments
 (0)