Skip to content

Commit ee6dca2

Browse files
authored
Merge pull request swiftlang#38552 from kavon/objc-thunk-hop-bug
2 parents 76a11cf + 8af69fb commit ee6dca2

File tree

3 files changed

+54
-4
lines changed

3 files changed

+54
-4
lines changed

lib/SILGen/SILGenBridging.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,8 +1569,10 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
15691569
if (thunk.hasDecl()) {
15701570
isolation = getActorIsolation(thunk.getDecl());
15711571
}
1572-
1573-
if (isolation) {
1572+
1573+
// A hop is only needed in the thunk if it is global-actor isolated.
1574+
// Native, instance-isolated async methods will hop in the prologue.
1575+
if (isolation && isolation->isGlobalActor()) {
15741576
emitHopToTargetActor(loc, *isolation, None);
15751577
}
15761578
}

test/Concurrency/actor_isolation_objc.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,16 @@ actor A {
4242
func g() { } // expected-note{{add '@objc' to expose this instance method to Objective-C}}
4343
@objc func h() async { }
4444
}
45+
46+
actor Dril: NSObject {
47+
// expected-note@+2 {{add 'async' to function 'postSynchronouslyTo(twitter:)' to make it asynchronous}}
48+
// expected-error@+1 {{actor-isolated instance method 'postSynchronouslyTo(twitter:)' cannot be @objc}}
49+
@objc func postSynchronouslyTo(twitter msg: String) -> Bool {
50+
return true
51+
}
52+
53+
@MainActor
54+
@objc func postFromMainActorTo(twitter msg: String) -> Bool {
55+
return true
56+
}
57+
}

test/SILGen/objc_async_from_swift.swift

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -I %S/Inputs/custom-modules -enable-experimental-concurrency -disable-availability-checking %s -verify | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -I %S/Inputs/custom-modules -enable-experimental-concurrency -disable-availability-checking %s -verify | %FileCheck --implicit-check-not=hop_to_executor --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s
22
// REQUIRES: concurrency
33
// REQUIRES: objc_interop
44

@@ -114,9 +114,44 @@ class SlowServerlet: SlowServer {
114114

115115
@FooActor
116116
class ActorConstrained: NSObject {
117-
// CHECK-LABEL: sil shared [thunk] [ossa] @$s{{.*}}16ActorConstrainedC3foo{{.*}}U_To
117+
// ActorConstrained.foo()
118+
// CHECK-LABEL: sil hidden [ossa] @$s{{.*}}16ActorConstrainedC3foo{{.*}} : $@convention(method) @async (@guaranteed ActorConstrained) -> Bool {
118119
// CHECK: hop_to_executor {{%.*}} : $FooActor
120+
121+
// @objc ActorConstrained.foo()
122+
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s{{.*}}16ActorConstrainedC3foo{{.*}}To : $@convention(objc_method) (@convention(block) (Bool) -> (), ActorConstrained) -> () {
123+
// CHECK: [[ASYNC_CLOS:%[0-9]+]] = function_ref @$s{{.*}}16ActorConstrainedC3foo{{.*}}U_To : $@convention(thin) @Sendable @async (@convention(block) (Bool) -> (), ActorConstrained) -> ()
124+
// CHECK: [[PRIMED_CLOS:%[0-9]+]] = partial_apply [callee_guaranteed] [[ASYNC_CLOS]](
125+
// CHECK: [[TASK_RUNNER:%[0-9]+]] = function_ref @$ss29_runTaskForBridgedAsyncMethodyyyyYaYbcnF
126+
// CHECK: apply [[TASK_RUNNER]]([[PRIMED_CLOS]])
127+
128+
// @objc closure #1 in ActorConstrained.foo()
129+
// CHECK-LABEL: sil shared [thunk] [ossa] @$s{{.*}}16ActorConstrainedC3foo{{.*}}U_To : $@convention(thin) @Sendable @async (@convention(block) (Bool) -> (), ActorConstrained) -> () {
130+
// CHECK: hop_to_executor {{%.*}} : $FooActor
119131
@objc func foo() async -> Bool {
120132
return true
121133
}
122134
}
135+
136+
137+
actor Dril: NSObject {
138+
// Dril.postTo(twitter:)
139+
// CHECK-LABEL: sil hidden [ossa] @$s{{.*}}4DrilC6postTo7twitter{{.*}} : $@convention(method) @async (@guaranteed String, @guaranteed Dril) -> Bool {
140+
// CHECK: hop_to_executor {{%.*}} : $Dril
141+
142+
// @objc Dril.postTo(twitter:)
143+
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s{{.*}}4DrilC6postTo7twitter{{.*}}To : $@convention(objc_method) (NSString, @convention(block) (Bool) -> (), Dril) -> () {
144+
// CHECK: [[ASYNC_CLOS:%[0-9]+]] = function_ref @$s{{.*}}4DrilC6postTo7twitter{{.*}}U_To : $@convention(thin) @Sendable @async (NSString, @convention(block) (Bool) -> (), Dril) -> ()
145+
// CHECK: [[PRIMED_CLOS:%[0-9]+]] = partial_apply [callee_guaranteed] [[ASYNC_CLOS]](
146+
// CHECK: [[TASK_RUNNER:%[0-9]+]] = function_ref @$ss29_runTaskForBridgedAsyncMethodyyyyYaYbcnF
147+
// CHECK: apply [[TASK_RUNNER]]([[PRIMED_CLOS]])
148+
@objc func postTo(twitter msg: String) async -> Bool {
149+
return true
150+
}
151+
152+
// this is known to not emit a hop in the objc thunk (rdar://80972126)
153+
@MainActor
154+
@objc func postFromMainActorTo(twitter msg: String) -> Bool {
155+
return true
156+
}
157+
}

0 commit comments

Comments
 (0)