Skip to content

Commit b93688c

Browse files
committed
Propagate "unsafe" global actors more freely.
Propagate "unsafe" global actors in the same manner as "safe" global actors. This propagates global actors much further (especially from classes and protocols), allowing more code to implicitly be known to be running on the given global actor. Fixes rdar://75548170.
1 parent 3fa7590 commit b93688c

File tree

2 files changed

+39
-27
lines changed

2 files changed

+39
-27
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2383,11 +2383,11 @@ static Optional<ActorIsolation> getIsolationFromAttributes(
23832383
}
23842384
}
23852385

2386-
// If the declaration is explicitly marked 'nonisolated', report it as
2387-
// independent.
2388-
if (nonisolatedAttr) {
2389-
return ActorIsolation::forIndependent(ActorIndependentKind::Safe);
2390-
}
2386+
// If the declaration is explicitly marked 'nonisolated', report it as
2387+
// independent.
2388+
if (nonisolatedAttr) {
2389+
return ActorIsolation::forIndependent(ActorIndependentKind::Safe);
2390+
}
23912391

23922392
// If the declaration is explicitly marked @actorIndependent, report it as
23932393
// independent.
@@ -2562,8 +2562,7 @@ ActorIsolation ActorIsolationRequest::evaluate(
25622562
}
25632563

25642564
// Function used when returning an inferred isolation.
2565-
auto inferredIsolation = [&](
2566-
ActorIsolation inferred, bool propagateUnsafe = false) {
2565+
auto inferredIsolation = [&](ActorIsolation inferred) {
25672566
// Add an implicit attribute to capture the actor isolation that was
25682567
// inferred, so that (e.g.) it will be printed and serialized.
25692568
ASTContext &ctx = value->getASTContext();
@@ -2576,13 +2575,6 @@ ActorIsolation ActorIsolationRequest::evaluate(
25762575
break;
25772576

25782577
case ActorIsolation::GlobalActorUnsafe:
2579-
if (!propagateUnsafe && !value->hasClangNode()) {
2580-
// Don't infer unsafe global actor isolation.
2581-
return ActorIsolation::forUnspecified();
2582-
}
2583-
2584-
LLVM_FALLTHROUGH;
2585-
25862578
case ActorIsolation::GlobalActor: {
25872579
auto typeExpr = TypeExpr::createImplicit(inferred.getGlobalActor(), ctx);
25882580
auto attr = CustomAttr::create(
@@ -2631,7 +2623,7 @@ ActorIsolation ActorIsolationRequest::evaluate(
26312623
if (auto wrapperInfo = var->getAttachedPropertyWrapperTypeInfo(0)) {
26322624
if (auto wrappedValue = wrapperInfo.valueVar) {
26332625
if (auto isolation = getActorIsolation(wrappedValue))
2634-
return inferredIsolation(isolation, /*propagateUnsafe=*/true);
2626+
return inferredIsolation(isolation);
26352627
}
26362628
}
26372629

@@ -2645,7 +2637,7 @@ ActorIsolation ActorIsolationRequest::evaluate(
26452637
if (!isa<ClassDecl>(backingNominal) ||
26462638
!cast<ClassDecl>(backingNominal)->isActor()) {
26472639
if (auto isolation = getActorIsolation(backingNominal))
2648-
return inferredIsolation(isolation, /*propagateUnsafe=*/true);
2640+
return inferredIsolation(isolation);
26492641
}
26502642
}
26512643
}
@@ -2659,7 +2651,7 @@ ActorIsolation ActorIsolationRequest::evaluate(
26592651
originalVar->getAttachedPropertyWrapperTypeInfo(0)) {
26602652
if (auto projectedValue = wrapperInfo.projectedValueVar) {
26612653
if (auto isolation = getActorIsolation(projectedValue))
2662-
return inferredIsolation(isolation, /*propagateUnsafe=*/true);
2654+
return inferredIsolation(isolation);
26632655
}
26642656
}
26652657
}
@@ -2669,8 +2661,7 @@ ActorIsolation ActorIsolationRequest::evaluate(
26692661
// If the declaration witnesses a protocol requirement that is isolated,
26702662
// use that.
26712663
if (auto witnessedIsolation = getIsolationFromWitnessedRequirements(value)) {
2672-
if (auto inferred = inferredIsolation(
2673-
*witnessedIsolation, /*propagateUnsafe=*/defaultIsolation))
2664+
if (auto inferred = inferredIsolation(*witnessedIsolation))
26742665
return inferred;
26752666
}
26762667

@@ -2710,10 +2701,8 @@ ActorIsolation ActorIsolationRequest::evaluate(
27102701
// If the declaration is in a nominal type (or extension thereof) that
27112702
// has isolation, use that.
27122703
if (auto selfTypeDecl = value->getDeclContext()->getSelfNominalTypeDecl()) {
2713-
auto selfTypeIsolation = getActorIsolation(selfTypeDecl);
2714-
if (!selfTypeIsolation.isUnspecified()) {
2704+
if (auto selfTypeIsolation = getActorIsolation(selfTypeDecl))
27152705
return inferredIsolation(selfTypeIsolation);
2716-
}
27172706
}
27182707
}
27192708

test/Concurrency/actor_isolation_unsafe.swift

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,31 @@ struct S4_P1: P1 {
3333
@SomeGlobalActor func onMainActor() { } // expected-error{{instance method 'onMainActor()' isolated to global actor 'SomeGlobalActor' can not satisfy corresponding requirement from protocol 'P1' isolated to global actor 'MainActor'}}
3434
}
3535

36+
@MainActor(unsafe)
37+
protocol P2 {
38+
func f() // expected-note{{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
39+
@actorIndependent func g()
40+
}
41+
42+
struct S5_P2: P2 {
43+
func f() { } // expected-note{{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
44+
func g() { }
45+
}
46+
47+
@actorIndependent func testP2(x: S5_P2, p2: P2) {
48+
p2.f() // expected-error{{instance method 'f()' isolated to global actor 'MainActor' can not be referenced from a non-isolated synchronous context}}
49+
p2.g() // OKAY
50+
x.f() // expected-error{{'f()' isolated to global actor 'MainActor' can not be referenced from a non-isolated synchronous context}}
51+
x.g() // OKAY
52+
}
53+
54+
func testP2_noconcurrency(x: S5_P2, p2: P2) {
55+
p2.f() // okay, not concurrency-related code
56+
p2.g() // okay
57+
x.f() // okay, not concurrency-related code
58+
x.g() // OKAY
59+
}
60+
3661
// ----------------------------------------------------------------------
3762
// Overriding and unsafe global actor
3863
// ----------------------------------------------------------------------
@@ -41,7 +66,7 @@ class C1 {
4166
}
4267

4368
class C2: C1 {
44-
override func method() { // expected-note{{overridden declaration is here}}
69+
override func method() { // expected-note 2{{overridden declaration is here}}
4570
globalSome() // okay
4671
}
4772
}
@@ -65,14 +90,12 @@ class C5: C1 {
6590

6691
class C6: C2 {
6792
// We didn't infer any actor isolation for C2.method().
68-
@SomeGlobalActor override func method() { // expected-error{{global actor 'SomeGlobalActor'-isolated instance method 'method()' has different actor isolation from non-actor-isolated overridden declaration}}
93+
@SomeGlobalActor override func method() { // expected-error{{global actor 'SomeGlobalActor'-isolated instance method 'method()' has different actor isolation from global actor 'MainActor'-isolated overridden declaration}}
6994
}
7095
}
7196

7297
class C7: C2 {
73-
// We didn't infer any actor isolation for C2.method(), but it's okay to be
74-
// explicitly unsafe.
75-
@SomeGlobalActor(unsafe) override func method() {
98+
@SomeGlobalActor(unsafe) override func method() { // expected-error{{global actor 'SomeGlobalActor'-isolated instance method 'method()' has different actor isolation from global actor 'MainActor'-isolated overridden declaration}}
7699
globalMain() // expected-error{{global function 'globalMain()' isolated to global actor 'MainActor' can not be referenced from different global actor 'SomeGlobalActor'}}
77100
globalSome() // okay
78101
}

0 commit comments

Comments
 (0)