Skip to content

Commit 29ffed2

Browse files
committed
IRGen: Fix reflection metadata for zero-sized enum cases
If an enum has a payload case with zero size, we treat it as an empty case for ABI purposes. Unfortunately, this meant that reflection metadata was incomplete for such cases, with a Mirror reporting that the enum value had zero children. Tweak the field type metadata emission slightly to preserve the payload type for such enum cases. Fixes <https://bugs.swift.org/browse/SR-12044> / <rdar://problem/58861157>.
1 parent 5ebfe3b commit 29ffed2

File tree

3 files changed

+34
-7
lines changed

3 files changed

+34
-7
lines changed

lib/IRGen/GenReflection.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
678678
const NominalTypeDecl *NTD;
679679

680680
void addFieldDecl(const ValueDecl *value, Type type,
681-
GenericSignature genericSig, bool indirect=false) {
681+
bool indirect=false) {
682682
reflection::FieldRecordFlags flags;
683683
flags.setIsIndirectCase(indirect);
684684
if (auto var = dyn_cast<VarDecl>(value))
@@ -689,6 +689,8 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
689689
if (!type) {
690690
B.addInt32(0);
691691
} else {
692+
auto genericSig = NTD->getGenericSignature();
693+
692694
// The standard library's Mirror demangles metadata from field
693695
// descriptors, so use MangledTypeRefRole::Metadata to ensure
694696
// runtime metadata is available.
@@ -722,8 +724,7 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
722724
auto properties = NTD->getStoredProperties();
723725
B.addInt32(properties.size());
724726
for (auto property : properties)
725-
addFieldDecl(property, property->getInterfaceType(),
726-
NTD->getGenericSignature());
727+
addFieldDecl(property, property->getInterfaceType());
727728
}
728729

729730
void layoutEnum() {
@@ -748,12 +749,11 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
748749
bool indirect = (enumCase.decl->isIndirect() ||
749750
enumDecl->isIndirect());
750751
addFieldDecl(enumCase.decl, enumCase.decl->getArgumentInterfaceType(),
751-
enumDecl->getGenericSignature(),
752752
indirect);
753753
}
754754

755755
for (auto enumCase : strategy.getElementsWithNoPayload()) {
756-
addFieldDecl(enumCase.decl, CanType(), nullptr);
756+
addFieldDecl(enumCase.decl, enumCase.decl->getArgumentInterfaceType());
757757
}
758758
}
759759

test/Reflection/typeref_lowering.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,11 @@
10411041
// CHECK-64-NEXT: (field name=noPayload offset=0
10421042
// CHECK-64-NEXT: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=252 bitwise_takable=1))
10431043
// CHECK-64-NEXT: (field name=sillyNoPayload offset=1
1044-
// CHECK-64-NEXT: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=252 bitwise_takable=1))
1044+
// CHECK-64-NEXT: (multi_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=252 bitwise_takable=1
1045+
// CHECK-64-NEXT: (field name=A offset=0
1046+
// CHECK-64-NEXT: (no_payload_enum size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
1047+
// CHECK-64-NEXT: (field name=B offset=0
1048+
// CHECK-64-NEXT: (no_payload_enum size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))))
10451049
// CHECK-64-NEXT: (field name=singleton offset=8
10461050
// CHECK-64-NEXT: (reference kind=strong refcounting=native))
10471051
// CHECK-64-NEXT: (field name=singlePayload offset=16

test/stdlib/Mirror.swift

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,28 @@ mirrors.test("Enum/SingletonNonGeneric/DefaultMirror") {
917917
}
918918
}
919919

920+
enum ZeroSizedEnumWithDefaultMirror {
921+
case π
922+
}
923+
924+
enum SingletonZeroSizedEnumWithDefaultMirror {
925+
case wrap(ZeroSizedEnumWithDefaultMirror)
926+
}
927+
928+
mirrors.test("Enum/SingletonZeroSizedEnumWithDefaultMirror/DefaultMirror") {
929+
do {
930+
let value = SingletonZeroSizedEnumWithDefaultMirror.wrap(.π)
931+
var output = ""
932+
dump(value, to: &output)
933+
934+
let expected =
935+
"▿ Mirror.SingletonZeroSizedEnumWithDefaultMirror.wrap\n" +
936+
" - wrap: Mirror.ZeroSizedEnumWithDefaultMirror.π\n"
937+
938+
expectEqual(expected, output)
939+
}
940+
}
941+
920942
enum SingletonGenericEnumWithDefaultMirror<T> {
921943
case OnlyOne(T)
922944
}
@@ -1994,7 +2016,8 @@ if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
19942016
testSTSDump(STSContainer.Cases<Int>.a(.init()),
19952017
STSContainer.Cases<Int>.a(.init()),
19962018
"""
1997-
- Mirror.STSContainer<Mirror.STSOuter>.Cases<Swift.Int>.a\n
2019+
▿ Mirror.STSContainer<Mirror.STSOuter>.Cases<Swift.Int>.a
2020+
- a: Mirror.STSOuter\n
19982021
""")
19992022

20002023
testSTSDump(STSContainer.Cases<Int>.b(.init()),

0 commit comments

Comments
 (0)