Skip to content

Commit b15adc5

Browse files
authored
Merge pull request #74396 from rjmccall/generic-objc-thunks-6.0
[6.0] Properly handle `@objc` thunks for generic classes and actors
2 parents 9b59951 + ed86f92 commit b15adc5

File tree

2 files changed

+52
-7
lines changed

2 files changed

+52
-7
lines changed

lib/SILGen/SILGenBridging.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,7 +1514,7 @@ SILFunction *SILGenFunction::emitNativeAsyncToForeignThunk(SILDeclRef thunk) {
15141514
.withAsync()
15151515
.withSendable()
15161516
.build();
1517-
auto closureTy = objcFnTy->getWithExtInfo(closureExtInfo);
1517+
auto closureTy = objcInfo.SILFnType->getWithExtInfo(closureExtInfo);
15181518

15191519
SmallString<64> closureName(F.getName().begin(), F.getName().end());
15201520
// Trim off the thunk suffix and mangle this like a closure nested inside the
@@ -1541,7 +1541,7 @@ SILFunction *SILGenFunction::emitNativeAsyncToForeignThunk(SILDeclRef thunk) {
15411541
IsNotRuntimeAccessible);
15421542

15431543
auto closureRef = B.createFunctionRef(loc, closure);
1544-
1544+
15451545
auto closureVal = B.createPartialApply(loc, closureRef, subs,
15461546
closureArgs,
15471547
ParameterConvention::Direct_Guaranteed);
@@ -1581,15 +1581,17 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
15811581
}
15821582
}
15831583

1584+
// Use the same generic environment as the native entry point.
1585+
// We need to set this before we can call things like
1586+
// F.getForwardingSubstitutionMap().
1587+
F.setGenericEnvironment(SGM.Types.getConstantGenericEnvironment(native));
1588+
15841589
auto nativeInfo = getConstantInfo(getTypeExpansionContext(), native);
15851590
auto subs = F.getForwardingSubstitutionMap();
15861591
auto substTy = nativeInfo.SILFnType->substGenericArgs(
15871592
SGM.M, subs, getTypeExpansionContext());
15881593
SILFunctionConventions substConv(substTy, SGM.M);
15891594

1590-
// Use the same generic environment as the native entry point.
1591-
F.setGenericEnvironment(SGM.Types.getConstantGenericEnvironment(native));
1592-
15931595
auto loc = thunk.getAsRegularLocation();
15941596
loc.markAutoGenerated();
15951597
Scope scope(Cleanups, CleanupLocation(loc));
@@ -1854,6 +1856,13 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
18541856
// The immediate function result is an empty tuple.
18551857
return SILUndef::get(&F, SGM.Types.getEmptyTupleType());
18561858
};
1859+
1860+
// If the function we're calling isn't actually polymorphic, drop the
1861+
// substitutions. This should only happen in concrete specializations.
1862+
if (subs && !nativeFn->getType().castTo<SILFunctionType>()->isPolymorphic()) {
1863+
assert(subs.getGenericSignature()->areAllParamsConcrete());
1864+
subs = SubstitutionMap();
1865+
}
18571866

18581867
if (!substTy->hasErrorResult()) {
18591868
// Create the apply.

test/SILGen/objc_generic_class.swift

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
// RUN: %target-swift-emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s
1+
// RUN: %target-swift-emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -disable-availability-checking | %FileCheck %s
22

33
// REQUIRES: objc_interop
4+
// REQUIRES: concurrency
45

56
import gizmo
67

@@ -11,9 +12,23 @@ import gizmo
1112
// CHECK-NOT: sil hidden [ossa] @$sSo7GenericCfd
1213
// CHECK-NOT: sil hidden [ossa] @$sSo8NSObjectCfd
1314

14-
class Generic<T>: NSObject {
15+
class Generic<T>: NSObject, ObjCProtocol {
1516
var x: Int = 10
1617

18+
// CHECK-LABEL: sil private [thunk] [ossa] @$s18objc_generic_class7GenericC5evokeyyFTo : $@convention(objc_method) <T> (Generic<T>) -> () {
19+
// CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class7GenericC5evokeyyF
20+
// CHECK-NEXT: apply [[FN]]<T>
21+
func evoke() {}
22+
23+
// CHECK-LABEL: sil private [thunk] [ossa] @$s18objc_generic_class7GenericC10evokeAsyncyyYaFTo : $@convention(objc_method) <T> (@convention(block) () -> (), Generic<T>) -> () {
24+
// CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class7GenericC10evokeAsyncyyYaFyyYacfU_To
25+
// CHECK-NEXT: partial_apply [callee_guaranteed] [[FN]]<T>
26+
27+
// CHECK-LABEL: sil shared [thunk] [ossa] @$s18objc_generic_class7GenericC10evokeAsyncyyYaFyyYacfU_To : $@convention(thin) @Sendable @async <T> (@convention(block) () -> (), Generic<T>) -> ()
28+
// CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class7GenericC10evokeAsyncyyYaF : $@convention(method) @async <τ_0_0> (@guaranteed Generic<τ_0_0>) -> ()
29+
// CHECK-NEXT: apply [[FN]]<T>
30+
func evokeAsync() async {}
31+
1732
// CHECK-LABEL: sil hidden [ossa] @$s18objc_generic_class7GenericCfD : $@convention(method) <T> (@owned Generic<T>) -> () {
1833
// CHECK: bb0({{%.*}} : @owned $Generic<T>):
1934
// CHECK: } // end sil function '$s18objc_generic_class7GenericCfD'
@@ -33,6 +48,11 @@ class Generic<T>: NSObject {
3348
// CHECK-NOT: sil hidden [ossa] @$s18objc_generic_class7GenericCfd
3449
// CHECK-NOT: sil hidden [ossa] @$sSo8NSObjectCfd
3550

51+
@objc protocol ObjCProtocol {
52+
func evoke()
53+
func evokeAsync() async
54+
}
55+
3656
// CHECK-LABEL: sil hidden [ossa] @$s18objc_generic_class11SubGeneric1CfD : $@convention(method) <U, V> (@owned SubGeneric1<U, V>) -> () {
3757
// CHECK: bb0([[SELF:%.*]] : @owned $SubGeneric1<U, V>):
3858
// CHECK: [[SUPER_DEALLOC:%.*]] = objc_super_method [[SELF]] : $SubGeneric1<U, V>, #Generic.deinit!deallocator.foreign : <T> (Generic<T>) -> () -> (), $@convention(objc_method) <τ_0_0> (Generic<τ_0_0>) -> ()
@@ -51,3 +71,19 @@ public extension GenericStruct where T == String {
5171
@objc public func f() -> String { "hello" }
5272
}
5373
}
74+
75+
// rdar://129187133 - handle generic @objc thunks properly
76+
actor GenericActor<T> : SendableObjCProtocol {
77+
// CHECK-LABEL: sil private [thunk] [ossa] @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaFTo : $@convention(objc_method) <T> (@convention(block) () -> (), @sil_isolated GenericActor<T>) -> ()
78+
// CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaFyyYacfU_To : $@convention(thin) @Sendable @async <τ_0_0> (@convention(block) () -> (), @sil_isolated GenericActor<τ_0_0>) -> ()
79+
// CHECK-NEXT: partial_apply [callee_guaranteed] [[FN]]<T>
80+
func evokeAsync() async {}
81+
82+
// CHECK-LABEL: sil shared [thunk] [ossa] @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaFyyYacfU_To : $@convention(thin) @Sendable @async <T> (@convention(block) () -> (), @sil_isolated GenericActor<T>) -> ()
83+
// CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaF : $@convention(method) @async <τ_0_0> (@sil_isolated @guaranteed GenericActor<τ_0_0>) -> ()
84+
// CHECK-NEXT: apply [[FN]]<T>
85+
}
86+
87+
@objc protocol SendableObjCProtocol : Sendable {
88+
func evokeAsync() async
89+
}

0 commit comments

Comments
 (0)