Skip to content

Commit 35a41ab

Browse files
committed
[Concurrency] References to nonisolated(nonsending) properties don't leave caller's isolation
Make sure that referencing `nonisolated(nonsending)` properties, especially through a witness is as not treated as leaving the isolation domain of the caller. Resolves: rdar://153922620
1 parent 857ed26 commit 35a41ab

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7919,6 +7919,9 @@ ActorReferenceResult ActorReferenceResult::forReference(
79197919
getInnermostIsolatedContext(fromDC, getClosureActorIsolation);
79207920
}
79217921

7922+
if (declIsolation.isCallerIsolationInheriting())
7923+
return forSameConcurrencyDomain(declIsolation, options);
7924+
79227925
// When the declaration is not actor-isolated, it can always be accessed
79237926
// directly.
79247927
if (!declIsolation.isActorIsolated()) {
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// RUN: %target-swift-emit-silgen %s -swift-version 6 -target %target-swift-5.1-abi-triple | %FileCheck %s
2+
3+
// REQUIRES: asserts
4+
// REQUIRES: concurrency
5+
6+
protocol P {
7+
nonisolated(nonsending) var prop: String { get async }
8+
nonisolated(nonsending) func fn() async
9+
}
10+
11+
struct S: P {
12+
var prop: String {
13+
get async { "" }
14+
}
15+
16+
func fn() async {
17+
}
18+
}
19+
20+
// CHECK-LABEL: sil hidden [ossa] @$s9witnesses21testMainActorDispatch1tyx_tYaAA1PRzlF : $@convention(thin) @async <T where T : P> (@in_guaranteed T) -> ()
21+
// CHECK: [[MAIN_ACTOR_TYPE:%.*]] = metatype $@thick MainActor.Type
22+
// CHECK: [[MAIN_ACTOR:%.*]] = apply {{.*}}([[MAIN_ACTOR_TYPE]]) : $@convention(method) (@thick MainActor.Type) -> @owned MainActor
23+
// CHECK-NEXT: [[BORROWED_MAIN_ACTOR:%.*]] = begin_borrow [[MAIN_ACTOR]]
24+
// CHECK-NEXT: hop_to_executor [[BORROWED_MAIN_ACTOR]]
25+
// CHECK-NEXT: [[MAIN_ACTOR_COPY:%.*]] = copy_value [[BORROWED_MAIN_ACTOR]]
26+
// CHECK-NEXT: [[ERASED_TO_ACTOR:%.*]] = init_existential_ref [[MAIN_ACTOR_COPY]] : $MainActor : $MainActor, $any Actor
27+
// CHECK-NEXT: [[CONTEXT_ISOLATION:%.*]] = enum $Optional<any Actor>, #Optional.some!enumelt, [[ERASED_TO_ACTOR]]
28+
// CHECK-NEXT: [[PROP_WITNESS:%.*]] = witness_method $T, #P.prop!getter : <Self where Self : P> (Self) -> () async -> String : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> @owned String
29+
// CHECK-NEXT: {{.*}} = apply [[PROP_WITNESS]]<T>([[CONTEXT_ISOLATION]], %0) : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> @owned String
30+
// CHECK: hop_to_executor [[BORROWED_MAIN_ACTOR]]
31+
// CHECK: [[MAIN_ACTOR_COPY:%.*]] = copy_value [[BORROWED_MAIN_ACTOR]]
32+
// CHECK-NEXT: [[ERASED_TO_ACTOR:%.*]] = init_existential_ref [[MAIN_ACTOR_COPY]] : $MainActor : $MainActor, $any Actor
33+
// CHECK-NEXT: [[CONTEXT_ISOLATION:%.*]] = enum $Optional<any Actor>, #Optional.some!enumelt, [[ERASED_TO_ACTOR]]
34+
// CHECK-NEXT: [[FN_WITNESS:%.*]] = witness_method $T, #P.fn : <Self where Self : P> (Self) -> () async -> () : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> ()
35+
// CHECK-NEXT: {{.*}} = apply [[FN_WITNESS]]<T>([[CONTEXT_ISOLATION]], %0) : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> ()
36+
// CHECK: } // end sil function '$s9witnesses21testMainActorDispatch1tyx_tYaAA1PRzlF'
37+
@MainActor
38+
func testMainActorDispatch<T: P>(t: T) async {
39+
_ = await t.prop
40+
_ = await t.fn()
41+
}
42+
43+
// CHECK-LABEL: sil hidden [ossa] @$s9witnesses19testGenericExecutor1tyx_tYaAA1PRzlF : $@convention(thin) @async <T where T : P> (@in_guaranteed T) -> ()
44+
// CHECK: [[CONTEXT_ISOLATION:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
45+
// CHECK-NEXT: hop_to_executor [[CONTEXT_ISOLATION]]
46+
// CHECK-NEXT: [[ISOLATION_ERASED_TO_ACTOR:%.*]] = enum $Optional<any Actor>, #Optional.none!enumelt
47+
// CHECK-NEXT: [[PROP_WITNESS:%.*]] = witness_method $T, #P.prop!getter : <Self where Self : P> (Self) -> () async -> String : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> @owned String
48+
// CHECK-NEXT: {{.*}} = apply [[PROP_WITNESS]]<T>([[ISOLATION_ERASED_TO_ACTOR]], %0) : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> @owned String
49+
// CHECK-NEXT: hop_to_executor [[CONTEXT_ISOLATION]]
50+
// CHECK: [[ISOLATION_ERASED_TO_ACTOR:%.*]] = enum $Optional<any Actor>, #Optional.none!enumelt
51+
// CHECK-NEXT: [[FN_WITNESS:%.*]] = witness_method $T, #P.fn : <Self where Self : P> (Self) -> () async -> () : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> ()
52+
// CHECK-NEXT: {{.*}} = apply [[FN_WITNESS]]<T>([[ISOLATION_ERASED_TO_ACTOR]], %0) : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> ()
53+
// CHECK: } // end sil function '$s9witnesses19testGenericExecutor1tyx_tYaAA1PRzlF'
54+
func testGenericExecutor<T: P>(t: T) async {
55+
_ = await t.prop
56+
_ = await t.fn()
57+
}
58+
59+
actor Test {
60+
// CHECK-LABEL: sil hidden [ossa] @$s9witnesses4TestC4test1tyx_tYaAA1PRzlF : $@convention(method) @async <T where T : P> (@in_guaranteed T, @sil_isolated @guaranteed Test) -> ()
61+
// CHECK: bb0(%0 : $*T, [[ACTOR:%.*]] : @guaranteed $Test):
62+
// CHECK: hop_to_executor [[ACTOR]]
63+
// CHECK-NEXT: [[ACTOR_COPY:%.*]] = copy_value [[ACTOR]]
64+
// CHECK-NEXT: [[ERASED_TO_ACTOR:%.*]] = init_existential_ref [[ACTOR_COPY]] : $Test : $Test, $any Actor
65+
// CHECK-NEXT: [[CONTEXT_ISOLATION:%.*]] = enum $Optional<any Actor>, #Optional.some!enumelt, [[ERASED_TO_ACTOR]]
66+
// CHECK-NEXT: [[PROP_WITNESS:%.*]] = witness_method $T, #P.prop!getter : <Self where Self : P> (Self) -> () async -> String : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> @owned String
67+
// CHECK-NEXT: {{.*}} = apply [[PROP_WITNESS]]<T>([[CONTEXT_ISOLATION]], %0) : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> @owned String
68+
// CHECK: hop_to_executor [[ACTOR]]
69+
// CHECK: [[ACTOR_COPY:%.*]] = copy_value [[ACTOR]]
70+
// CHECK-NEXT: [[ERASED_TO_ACTOR:%.*]] = init_existential_ref [[ACTOR_COPY]] : $Test : $Test, $any Actor
71+
// CHECK-NEXT: [[CONTEXT_ISOLATION:%.*]] = enum $Optional<any Actor>, #Optional.some!enumelt, [[ERASED_TO_ACTOR]]
72+
// CHECK-NEXT: [[FN_WITNESS:%.*]] = witness_method $T, #P.fn : <Self where Self : P> (Self) -> () async -> () : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> ()
73+
// CHECK-NEXT: {{.*}} = apply [[FN_WITNESS]]<T>([[CONTEXT_ISOLATION]], %0) : $@convention(witness_method: P) @async <τ_0_0 where τ_0_0 : P> (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed τ_0_0) -> ()
74+
// CHECK: } // end sil function '$s9witnesses4TestC4test1tyx_tYaAA1PRzlF'
75+
func test<T: P>(t: T) async {
76+
_ = await t.prop
77+
_ = await t.fn()
78+
}
79+
}
80+
81+
// CHECK-LABEL: sil hidden [ossa] @$s9witnesses14testDirectCall1syAA1SV_tYaF : $@convention(thin) @async (S) -> ()
82+
// CHECK: [[MAIN_ACTOR_TYPE:%.*]] = metatype $@thick MainActor.Type
83+
// CHECK: [[MAIN_ACTOR:%.*]] = apply {{.*}}([[MAIN_ACTOR_TYPE]]) : $@convention(method) (@thick MainActor.Type) -> @owned MainActor
84+
// CHECK-NEXT: [[BORROWED_MAIN_ACTOR:%.*]] = begin_borrow [[MAIN_ACTOR]]
85+
// CHECK-NEXT: hop_to_executor [[BORROWED_MAIN_ACTOR]]
86+
// CHECK-NEXT: [[MAIN_ACTOR_COPY:%.*]] = copy_value [[BORROWED_MAIN_ACTOR]]
87+
// CHECK-NEXT: [[ERASED_TO_ACTOR:%.*]] = init_existential_ref [[MAIN_ACTOR_COPY]] : $MainActor : $MainActor, $any Actor
88+
// CHECK-NEXT: [[CONTEXT_ISOLATION:%.*]] = enum $Optional<any Actor>, #Optional.some!enumelt, [[ERASED_TO_ACTOR]]
89+
// CHECK: [[PROP_REF:%.*]] = function_ref @$s9witnesses1SV4propSSvg : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, S) -> @owned String
90+
// CHECK-NEXT: {{.*}} = apply [[PROP_REF]]([[CONTEXT_ISOLATION]], %0) : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, S) -> @owned String
91+
// CHECK: hop_to_executor [[BORROWED_MAIN_ACTOR]]
92+
// CHECK: [[MAIN_ACTOR_COPY:%.*]] = copy_value [[BORROWED_MAIN_ACTOR]]
93+
// CHECK-NEXT: [[ERASED_TO_ACTOR:%.*]] = init_existential_ref [[MAIN_ACTOR_COPY]] : $MainActor : $MainActor, $any Actor
94+
// CHECK-NEXT: [[CONTEXT_ISOLATION:%.*]] = enum $Optional<any Actor>, #Optional.some!enumelt, [[ERASED_TO_ACTOR]]
95+
// CHECK: [[FN_REF:%.*]] = function_ref @$s9witnesses1SV2fnyyYaF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, S) -> ()
96+
// CHECK-NEXT: {{.*}} = apply [[FN_REF]]([[CONTEXT_ISOLATION]], %0) : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, S) -> ()
97+
// CHECK: } // end sil function '$s9witnesses14testDirectCall1syAA1SV_tYaF'
98+
@MainActor
99+
func testDirectCall(s: S) async {
100+
_ = await s.prop
101+
_ = await s.fn()
102+
}

0 commit comments

Comments
 (0)