Skip to content

Commit 67449c9

Browse files
authored
Merge pull request #82432 from xedin/nonisolated_nonsending-fixes-6.2
[6.2][Concurrency] A few `nonisolated(nonsending)` fixes
2 parents ef622dd + 61c480f commit 67449c9

File tree

3 files changed

+166
-1
lines changed

3 files changed

+166
-1
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5271,9 +5271,18 @@ getIsolationFromWitnessedRequirements(ValueDecl *value) {
52715271
case ActorIsolation::Erased:
52725272
llvm_unreachable("requirement cannot have erased isolation");
52735273

5274+
case ActorIsolation::CallerIsolationInheriting: {
5275+
if (value->isAsync())
5276+
break;
5277+
5278+
// It's possible to witness requirement with an non-async
5279+
// declaration, in such cases `nonisolated(nonsending)` does
5280+
// not apply.
5281+
continue;
5282+
}
5283+
52745284
case ActorIsolation::GlobalActor:
52755285
case ActorIsolation::Nonisolated:
5276-
case ActorIsolation::CallerIsolationInheriting:
52775286
case ActorIsolation::NonisolatedUnsafe:
52785287
break;
52795288
}
@@ -8008,6 +8017,9 @@ ActorReferenceResult ActorReferenceResult::forReference(
80088017
getInnermostIsolatedContext(fromDC, getClosureActorIsolation);
80098018
}
80108019

8020+
if (declIsolation.isCallerIsolationInheriting())
8021+
return forSameConcurrencyDomain(declIsolation, options);
8022+
80118023
// When the declaration is not actor-isolated, it can always be accessed
80128024
// directly.
80138025
if (!declIsolation.isActorIsolated()) {

test/Concurrency/attr_execution/protocols_silgen.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ protocol P {
1313
@MainActor func mainActorTest() async
1414
}
1515

16+
protocol Q {
17+
nonisolated(nonsending) var test: String { get async throws }
18+
nonisolated(nonsending) func fnTest() async
19+
}
20+
1621
struct AllDefault : P {
1722
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s21attr_execution_silgen10AllDefaultVAA1PA2aDP10callerTestyyYaFTW : $@convention(witness_method: P) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed AllDefault) -> () {
1823
// CHECK: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>, [[SELF:%.*]] : $*AllDefault):
@@ -120,3 +125,49 @@ struct AllMainActor : P {
120125
// CHECK: } // end sil function '$s21attr_execution_silgen12AllMainActorVAA1PA2aDP04mainF4TestyyYaFTW'
121126
@MainActor func mainActorTest() async {}
122127
}
128+
129+
// Make sure that stored/non-async witness doesn't inherit `nonisolated(nonsending)` but thunk dismatches correctly
130+
131+
struct TestWitnessWithStorage: Q {
132+
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s21attr_execution_silgen22TestWitnessWithStorageV4testSSvg : $@convention(method) (@guaranteed TestWitnessWithStorage) -> @owned String
133+
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s21attr_execution_silgen22TestWitnessWithStorageV4testSSvs : $@convention(method) (@owned String, @inout TestWitnessWithStorage) -> ()
134+
var test: String
135+
136+
// CHECK-LABEL: sil hidden [ossa] @$s21attr_execution_silgen22TestWitnessWithStorageV02fnD0yyF : $@convention(method) (@guaranteed TestWitnessWithStorage) -> ()
137+
func fnTest() {}
138+
139+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s21attr_execution_silgen22TestWitnessWithStorageVAA1QA2aDP4testSSvgTW : $@convention(witness_method: Q) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed TestWitnessWithStorage) -> (@owned String, @error any Error)
140+
// CHECK: bb0([[ISOLATION:%.*]] : @guaranteed $Optional<any Actor>, [[SELF:%.*]] : $*TestWitnessWithStorage):
141+
// CHECK-NEXT: [[BORROWED_SELF:%.*]] = load_borrow [[SELF]]
142+
// CHECK: [[WITNESS:%.*]] = function_ref @$s21attr_execution_silgen22TestWitnessWithStorageV4testSSvg : $@convention(method) (@guaranteed TestWitnessWithStorage) -> @owned String
143+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[WITNESS]]([[BORROWED_SELF]]) : $@convention(method) (@guaranteed TestWitnessWithStorage) -> @owned String
144+
// CHECK-NEXT: end_borrow [[BORROWED_SELF]]
145+
// CHECK-NEXT: return [[RESULT]]
146+
// CHECK-NEXT: } // end sil function '$s21attr_execution_silgen22TestWitnessWithStorageVAA1QA2aDP4testSSvgTW'
147+
148+
// CHECK: sil private [transparent] [thunk] [ossa] @$s21attr_execution_silgen22TestWitnessWithStorageVAA1QA2aDP02fnD0yyYaFTW : $@convention(witness_method: Q) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed TestWitnessWithStorage) -> ()
149+
// CHECK: bb0([[ISOLATION:%.*]] : @guaranteed $Optional<any Actor>, [[SELF:%.*]] : $*TestWitnessWithStorage):
150+
// CHECK-NEXT: [[BORROWED_SELF]] = load_borrow [[SELF]]
151+
// CHECK: [[WITNESS:%.*]] = function_ref @$s21attr_execution_silgen22TestWitnessWithStorageV02fnD0yyF : $@convention(method) (@guaranteed TestWitnessWithStorage) -> ()
152+
// CHECK-NEXT: {{.*}} = apply [[WITNESS]]([[BORROWED_SELF]]) : $@convention(method) (@guaranteed TestWitnessWithStorage) -> ()
153+
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
154+
// CHECK-NEXT: end_borrow [[BORROWED_SELF]]
155+
// CHECK-NEXT: return [[RESULT]]
156+
// CHECK-NEXT: } // end sil function '$s21attr_execution_silgen22TestWitnessWithStorageVAA1QA2aDP02fnD0yyYaFTW'
157+
}
158+
159+
struct TestSyncWitness: Q {
160+
// CHECK-LABEL: sil hidden [ossa] @$s21attr_execution_silgen15TestSyncWitnessV4testSSvg : $@convention(method) (TestSyncWitness) -> @owned String
161+
var test: String { "" }
162+
163+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s21attr_execution_silgen15TestSyncWitnessVAA1QA2aDP4testSSvgTW : $@convention(witness_method: Q) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed TestSyncWitness) -> (@owned String, @error any Error)
164+
// CHECK: bb0([[ISOLATION:%.*]] : @guaranteed $Optional<any Actor>, [[SELF:%.*]] : $*TestSyncWitness):
165+
// CHECK-NEXT: [[BORROWED_SELF:%.*]] = load [trivial] [[SELF]]
166+
// CHECK: [[WITNESS:%.*]] = function_ref @$s21attr_execution_silgen15TestSyncWitnessV4testSSvg : $@convention(method) (TestSyncWitness) -> @owned String
167+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[WITNESS]]([[BORROWED_SELF]]) : $@convention(method) (TestSyncWitness) -> @owned String
168+
// CHECK-NEXT: return [[RESULT]]
169+
// CHECK-NEXT: } // end sil function '$s21attr_execution_silgen15TestSyncWitnessVAA1QA2aDP4testSSvgTW'
170+
171+
// Tested in the `TestWitnessWithStorage`
172+
func fnTest() {}
173+
}
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)