Skip to content

Commit 5c08690

Browse files
committed
IRGen: Fix capture descriptor emission for @pseudogeneric functions
Pseudogeneric functions do not have runtime type metadata in their closure context, so don't try to emit metadata sources in the capture descriptor for reflection. Also, erase generic type parameters in capture types down to AnyObject, since the reflection library won't be able to substitute them.
1 parent 5dd5d82 commit 5c08690

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

lib/IRGen/GenReflection.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,10 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
633633
MetadataSourceMap getMetadataSourceMap() {
634634
MetadataSourceMap SourceMap;
635635

636-
if (!OrigCalleeType->isPolymorphic())
636+
// Generic parameters of pseudogeneric functions do not have
637+
// runtime metadata.
638+
if (!OrigCalleeType->isPolymorphic() ||
639+
OrigCalleeType->isPseudogeneric())
637640
return SourceMap;
638641

639642
// Any generic parameters that are not fulfilled are passed in via the
@@ -702,6 +705,19 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
702705

703706
for (auto ElementType : getElementTypes()) {
704707
auto SwiftType = ElementType.getSwiftRValueType();
708+
709+
// Erase pseudogeneric captures down to AnyObject.
710+
if (OrigCalleeType->isPseudogeneric()) {
711+
SwiftType = SwiftType.transform([&](Type t) -> Type {
712+
if (auto *archetype = t->getAs<ArchetypeType>()) {
713+
assert(archetype->requiresClass() && "don't know what to do");
714+
return IGM.Context.getProtocol(KnownProtocolKind::AnyObject)
715+
->getDeclaredType();
716+
}
717+
return t;
718+
})->getCanonicalType();
719+
}
720+
705721
auto InterfaceType = Caller.mapTypeOutOfContext(SwiftType);
706722
CaptureTypes.push_back(InterfaceType->getCanonicalType());
707723
}

test/Reflection/capture_descriptors.sil

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,28 @@ sil_vtable GenericClass {}
192192
// CHECK-NEXT: (reference_capture index=0))
193193

194194

195+
// Pseudogeneric caller and pseudogeneric callee -- type parameters are
196+
// erased at runtime.
197+
198+
sil @pseudogeneric_callee : $@convention(thin) @pseudogeneric <T : AnyObject, U : AnyObject> (@owned T, @owned U) -> () {
199+
bb0(%t: $T, %u: $U):
200+
%12 = tuple ()
201+
return %12 : $()
202+
}
203+
204+
sil @pseudogeneric_caller : $@convention(thin) @pseudogeneric <A : AnyObject, B : AnyObject, C : AnyObject> (@owned A, @owned B) -> @owned @pseudogeneric @callee_owned () -> () {
205+
bb0(%a: $A, %b: $B):
206+
%f = function_ref @pseudogeneric_callee : $@convention(thin) @pseudogeneric <T : AnyObject, U : AnyObject> (@owned T, @owned U) -> ()
207+
%c = partial_apply %f<A, B>(%a, %b) : $@convention(thin) @pseudogeneric <A : AnyObject, B : AnyObject> (@owned A, @owned B) -> ()
208+
return %c : $@pseudogeneric @callee_owned () -> ()
209+
}
210+
211+
// CHECK: - Capture types:
212+
// CHECK-NEXT: (protocol Swift.AnyObject)
213+
// CHECK-NEXT: (protocol Swift.AnyObject)
214+
// CHECK-NEXT: - Metadata sources:
215+
216+
195217
// Capturing lowered function types
196218

197219
sil @function_callee : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method) () -> ()) -> () {

0 commit comments

Comments
 (0)