Skip to content

Commit 862ae5f

Browse files
committed
Properly handle @objc thunks for generic classes and actors
Fixes rdar://129187133
1 parent 3889ede commit 862ae5f

File tree

2 files changed

+51
-7
lines changed

2 files changed

+51
-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
@@ -1535,7 +1535,7 @@ SILFunction *SILGenFunction::emitNativeAsyncToForeignThunk(SILDeclRef thunk) {
15351535
IsNotDistributed, IsNotRuntimeAccessible);
15361536

15371537
auto closureRef = B.createFunctionRef(loc, closure);
1538-
1538+
15391539
auto closureVal = B.createPartialApply(loc, closureRef, subs,
15401540
closureArgs,
15411541
ParameterConvention::Direct_Guaranteed);
@@ -1575,15 +1575,17 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
15751575
}
15761576
}
15771577

1578+
// Use the same generic environment as the native entry point.
1579+
// We need to set this before we can call things like
1580+
// F.getForwardingSubstitutionMap().
1581+
F.setGenericEnvironment(SGM.Types.getConstantGenericEnvironment(native));
1582+
15781583
auto nativeInfo = getConstantInfo(getTypeExpansionContext(), native);
15791584
auto subs = F.getForwardingSubstitutionMap();
15801585
auto substTy = nativeInfo.SILFnType->substGenericArgs(
15811586
SGM.M, subs, getTypeExpansionContext());
15821587
SILFunctionConventions substConv(substTy, SGM.M);
15831588

1584-
// Use the same generic environment as the native entry point.
1585-
F.setGenericEnvironment(SGM.Types.getConstantGenericEnvironment(native));
1586-
15871589
auto loc = thunk.getAsRegularLocation();
15881590
loc.markAutoGenerated();
15891591
Scope scope(Cleanups, CleanupLocation(loc));
@@ -1848,6 +1850,13 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
18481850
// The immediate function result is an empty tuple.
18491851
return SILUndef::get(&F, SGM.Types.getEmptyTupleType());
18501852
};
1853+
1854+
// If the function we're calling isn't actually polymorphic, drop the
1855+
// substitutions. This should only happen in concrete specializations.
1856+
if (subs && !nativeFn->getType().castTo<SILFunctionType>()->isPolymorphic()) {
1857+
assert(subs.getGenericSignature()->areAllParamsConcrete());
1858+
subs = SubstitutionMap();
1859+
}
18511860

18521861
if (!substTy->hasErrorResult()) {
18531862
// Create the apply.

test/SILGen/objc_generic_class.swift

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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
44

@@ -11,9 +11,23 @@ import gizmo
1111
// CHECK-NOT: sil hidden [ossa] @$sSo7GenericCfd
1212
// CHECK-NOT: sil hidden [ossa] @$sSo8NSObjectCfd
1313

14-
class Generic<T>: NSObject {
14+
class Generic<T>: NSObject, ObjCProtocol {
1515
var x: Int = 10
1616

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

50+
@objc protocol ObjCProtocol {
51+
func evoke()
52+
func evokeAsync() async
53+
}
54+
3655
// CHECK-LABEL: sil hidden [ossa] @$s18objc_generic_class11SubGeneric1CfD : $@convention(method) <U, V> (@owned SubGeneric1<U, V>) -> () {
3756
// CHECK: bb0([[SELF:%.*]] : @owned $SubGeneric1<U, V>):
3857
// 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 +70,19 @@ public extension GenericStruct where T == String {
5170
@objc public func f() -> String { "hello" }
5271
}
5372
}
73+
74+
// rdar://129187133 - handle generic @objc thunks properly
75+
actor GenericActor<T> : SendableObjCProtocol {
76+
// CHECK-LABEL: sil private [thunk] [ossa] @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaFTo : $@convention(objc_method) <T> (@convention(block) () -> (), @sil_isolated GenericActor<T>) -> ()
77+
// CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaFyyYacfU_To : $@convention(thin) @Sendable @async <τ_0_0> (@convention(block) () -> (), @sil_isolated GenericActor<τ_0_0>) -> ()
78+
// CHECK-NEXT: partial_apply [callee_guaranteed] [[FN]]<T>
79+
func evokeAsync() async {}
80+
81+
// CHECK-LABEL: sil shared [thunk] [ossa] @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaFyyYacfU_To : $@convention(thin) @Sendable @async <T> (@convention(block) () -> (), @sil_isolated GenericActor<T>) -> ()
82+
// CHECK: [[FN:%.*]] = function_ref @$s18objc_generic_class12GenericActorC10evokeAsyncyyYaF : $@convention(method) @async <τ_0_0> (@sil_isolated @guaranteed GenericActor<τ_0_0>) -> ()
83+
// CHECK-NEXT: apply [[FN]]<T>
84+
}
85+
86+
@objc protocol SendableObjCProtocol : Sendable {
87+
func evokeAsync() async
88+
}

0 commit comments

Comments
 (0)