Skip to content

Commit 1232424

Browse files
authored
RemoteMirror generic multi-payload-enum fixes (#41903)
Apparently, RemoteMirror chokes on certain MPEs with generic payload types. It does not recognize the generic payload type so ends up defaulting to a zero size. This causes the overall enum size to be miscalculated unless there is another non-generic payload that's at least as large. The case below requires us to reprocess the metatype to "thicken" it. That process inadvertently lost information about the depth of generic nesting, which caused the RemoteMirror to be unable to resolve the type of `C.E.t` at runtime. ``` class C<T> { enum E<T> { case t(T) case u(Int) } var e: E<T>? } ``` Solution: add code to the thickening logic to recursively thicken parent types to preserve the nesting of generics. Resolves rdar://90490128
1 parent a5adc4c commit 1232424

File tree

2 files changed

+165
-1
lines changed

2 files changed

+165
-1
lines changed

stdlib/public/Reflection/TypeRef.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,8 +1061,12 @@ class ThickenMetatype
10611061
std::vector<const TypeRef *> GenericParams;
10621062
for (auto Param : BG->getGenericParams())
10631063
GenericParams.push_back(visit(Param));
1064+
auto parent = BG->getParent();
1065+
if (parent) {
1066+
parent = ThickenMetatype(Builder).visit(parent);
1067+
}
10641068
return BoundGenericTypeRef::create(Builder, BG->getMangledName(),
1065-
GenericParams);
1069+
GenericParams, parent);
10661070
}
10671071

10681072
const TypeRef *visitTupleTypeRef(const TupleTypeRef *T) {
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_MultiPayload_generic
3+
// RUN: %target-codesign %t/reflect_Enum_MultiPayload_generic
4+
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_MultiPayload_generic | tee /dev/stderr | %FileCheck %s --check-prefix=CHECK --check-prefix=X%target-ptrsize --dump-input=fail
6+
7+
// REQUIRES: reflection_test_support
8+
// REQUIRES: objc_interop
9+
// REQUIRES: executable_test
10+
// UNSUPPORTED: use_os_stdlib
11+
12+
import SwiftReflectionTest
13+
14+
struct S {
15+
var a: Int
16+
var b: Int
17+
var c: Int
18+
}
19+
20+
class ClassWithEnumDepth0<T> {
21+
enum E {
22+
case t(T)
23+
case u(Int)
24+
}
25+
var e: E?
26+
}
27+
28+
reflect(object: ClassWithEnumDepth0<S>())
29+
30+
// CHECK: Reflecting an object.
31+
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
32+
// CHECK-NEXT: Type reference:
33+
// CHECK-NEXT: (bound_generic_class reflect_Enum_MultiPayload_generic.ClassWithEnumDepth0
34+
// CHECK-NEXT: (struct reflect_Enum_MultiPayload_generic.S))
35+
36+
// X64: Type info:
37+
// X64-NEXT: (class_instance size=41 alignment=8 stride=48 num_extra_inhabitants=0 bitwise_takable=1
38+
// X64-NEXT: (field name=e offset=16
39+
// X64-NEXT: (single_payload_enum size=25 alignment=8 stride=32 num_extra_inhabitants=253 bitwise_takable=1
40+
// X64-NEXT: (case name=some index=0 offset=0
41+
// X64-NEXT: (multi_payload_enum size=25 alignment=8 stride=32 num_extra_inhabitants=254 bitwise_takable=1
42+
// X64-NEXT: (case name=t index=0 offset=0
43+
// X64-NEXT: (struct size=24 alignment=8 stride=24 num_extra_inhabitants=0 bitwise_takable=1
44+
// X64-NEXT: (field name=a offset=0
45+
// X64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
46+
// X64-NEXT: (field name=_value offset=0
47+
// X64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
48+
// X64-NEXT: (field name=b offset=8
49+
// X64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
50+
// X64-NEXT: (field name=_value offset=0
51+
// X64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
52+
// X64-NEXT: (field name=c offset=16
53+
// X64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
54+
// X64-NEXT: (field name=_value offset=0
55+
// X64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))))
56+
// X64-NEXT: (case name=u index=1 offset=0
57+
// X64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
58+
// X64-NEXT: (field name=_value offset=0
59+
// X64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))))
60+
// X64-NEXT: (case name=none index=1))))
61+
62+
// X32: Type info:
63+
// X32-NEXT: (class_instance size=21 alignment=4 stride=24 num_extra_inhabitants=0 bitwise_takable=1
64+
// X32-NEXT: (field name=e offset=8
65+
// X32-NEXT: (single_payload_enum size=13 alignment=4 stride=16 num_extra_inhabitants=253 bitwise_takable=1
66+
// X32-NEXT: (case name=some index=0 offset=0
67+
// X32-NEXT: (multi_payload_enum size=13 alignment=4 stride=16 num_extra_inhabitants=254 bitwise_takable=1
68+
// X32-NEXT: (case name=t index=0 offset=0
69+
// X32-NEXT: (struct size=12 alignment=4 stride=12 num_extra_inhabitants=0 bitwise_takable=1
70+
// X32-NEXT: (field name=a offset=0
71+
// X32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
72+
// X32-NEXT: (field name=_value offset=0
73+
// X32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
74+
// X32-NEXT: (field name=b offset=4
75+
// X32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
76+
// X32-NEXT: (field name=_value offset=0
77+
// X32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
78+
// X32-NEXT: (field name=c offset=8
79+
// X32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
80+
// X32-NEXT: (field name=_value offset=0
81+
// X32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))))
82+
// X32-NEXT: (case name=u index=1 offset=0
83+
// X32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
84+
// X32-NEXT: (field name=_value offset=0
85+
// X32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))))
86+
// X32-NEXT: (case name=none index=1))))
87+
88+
89+
class ClassWithEnumDepth1<T> {
90+
enum E<T> {
91+
case t(T)
92+
case u(Int)
93+
}
94+
var e: E<T>?
95+
}
96+
97+
reflect(object: ClassWithEnumDepth1<S>())
98+
99+
// CHECK: Reflecting an object.
100+
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
101+
// CHECK-NEXT: Type reference:
102+
// CHECK-NEXT: (bound_generic_class reflect_Enum_MultiPayload_generic.ClassWithEnumDepth1
103+
// CHECK-NEXT: (struct reflect_Enum_MultiPayload_generic.S))
104+
105+
// X64: Type info:
106+
// X64-NEXT: (class_instance size=41 alignment=8 stride=48 num_extra_inhabitants=0 bitwise_takable=1
107+
// X64-NEXT: (field name=e offset=16
108+
// X64-NEXT: (single_payload_enum size=25 alignment=8 stride=32 num_extra_inhabitants=253 bitwise_takable=1
109+
// X64-NEXT: (case name=some index=0 offset=0
110+
// X64-NEXT: (multi_payload_enum size=25 alignment=8 stride=32 num_extra_inhabitants=254 bitwise_takable=1
111+
// X64-NEXT: (case name=t index=0 offset=0
112+
// X64-NEXT: (struct size=24 alignment=8 stride=24 num_extra_inhabitants=0 bitwise_takable=1
113+
// X64-NEXT: (field name=a offset=0
114+
// X64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
115+
// X64-NEXT: (field name=_value offset=0
116+
// X64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
117+
// X64-NEXT: (field name=b offset=8
118+
// X64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
119+
// X64-NEXT: (field name=_value offset=0
120+
// X64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
121+
// X64-NEXT: (field name=c offset=16
122+
// X64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
123+
// X64-NEXT: (field name=_value offset=0
124+
// X64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))))
125+
// X64-NEXT: (case name=u index=1 offset=0
126+
// X64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
127+
// X64-NEXT: (field name=_value offset=0
128+
// X64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))))
129+
// X64-NEXT: (case name=none index=1))))
130+
131+
// X32: Type info:
132+
// X32-NEXT: (class_instance size=21 alignment=4 stride=24 num_extra_inhabitants=0 bitwise_takable=1
133+
// X32-NEXT: (field name=e offset=8
134+
// X32-NEXT: (single_payload_enum size=13 alignment=4 stride=16 num_extra_inhabitants=253 bitwise_takable=1
135+
// X32-NEXT: (case name=some index=0 offset=0
136+
// X32-NEXT: (multi_payload_enum size=13 alignment=4 stride=16 num_extra_inhabitants=254 bitwise_takable=1
137+
// X32-NEXT: (case name=t index=0 offset=0
138+
// X32-NEXT: (struct size=12 alignment=4 stride=12 num_extra_inhabitants=0 bitwise_takable=1
139+
// X32-NEXT: (field name=a offset=0
140+
// X32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
141+
// X32-NEXT: (field name=_value offset=0
142+
// X32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
143+
// X32-NEXT: (field name=b offset=4
144+
// X32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
145+
// X32-NEXT: (field name=_value offset=0
146+
// X32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
147+
// X32-NEXT: (field name=c offset=8
148+
// X32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
149+
// X32-NEXT: (field name=_value offset=0
150+
// X32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))))
151+
// X32-NEXT: (case name=u index=1 offset=0
152+
// X32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
153+
// X32-NEXT: (field name=_value offset=0
154+
// X32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))))
155+
// X32-NEXT: (case name=none index=1))))
156+
157+
doneReflecting()
158+
159+
// CHECK: Done.
160+

0 commit comments

Comments
 (0)