Skip to content

Commit 1772e77

Browse files
committed
IRGen: Fix multi-payload enum lowering
When we have a private resilient enum that is resilient because one of its payloads is resilient but we have disabled resilience in the context of lowering the enum as a class member (sigh), we must consider it's payload's layout enum in the minimal domain (ignore the private visibility) because we don't truly know the layout. rdar://41308521
1 parent 346cf80 commit 1772e77

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5258,6 +5258,12 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
52585258
// fixed-size from this resilience scope.
52595259
ResilienceExpansion layoutScope =
52605260
TC.IGM.getResilienceExpansionForLayout(theEnum);
5261+
if (TC.isCompletelyFragile()) {
5262+
// If we forced completely fragile layout we need to check the
5263+
// fixed-sized'ness in the minimal scope. Otherwise, we get wrong answer for
5264+
// private resilient enum types that have an resilient payload.
5265+
layoutScope = ResilienceExpansion::Minimal;
5266+
}
52615267

52625268
for (auto elt : theEnum->getAllElements()) {
52635269
numElements++;

test/IRGen/enum_resilience.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ import resilient_struct
2222
// ENUM_NOT_RES-NOT: @"$S14resilient_enum6MediumO6CanvasyA2CmFWC" =
2323

2424
// CHECK: %T15enum_resilience5ClassC = type <{ %swift.refcounted }>
25+
26+
// Because the enum is resilient we cannot pack the tag into the pointer inside of the resilient payload.
27+
// CHECK: %T15enum_resilience9ContainerC5Multi33_59077B69D65A4A3BEE0C93708067D5F0LLO.0 = type <{ [8 x i8], [1 x i8] }>
28+
2529
// CHECK: %T15enum_resilience9ReferenceV = type <{ %T15enum_resilience5ClassC* }>
2630

2731
// Public fixed layout struct contains a public resilient struct,
@@ -326,3 +330,18 @@ private enum ProtGenEnumWithSize<T: Prot> {
326330

327331
// CHECK-LABEL: define linkonce_odr hidden %T15enum_resilience19ProtGenEnumWithSize33_59077B69D65A4A3BEE0C93708067D5F0LLO* @"$S15enum_resilience19ProtGenEnumWithSize33_59077B69D65A4A3BEE0C93708067D5F0LLOyxGAA0C0RzlWOh"(%T15enum_resilience19ProtGenEnumWithSize
328332
// CHECK: ret %T15enum_resilience19ProtGenEnumWithSize33_59077B69D65A4A3BEE0C93708067D5F0LLO* %0
333+
334+
335+
public class Container {
336+
private enum Multi {
337+
case none
338+
case some(Container)
339+
case data(ResilientRef)
340+
}
341+
private var e: Multi
342+
var i: Int
343+
init() {
344+
e = .none
345+
i = 0
346+
}
347+
}

test/Inputs/resilient_struct.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,7 @@ public struct ResilientWeakRef {
8787
ref = r
8888
}
8989
}
90+
91+
public struct ResilientRef {
92+
public var r: Referent
93+
}

test/Interpreter/enum_resilience.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,4 +436,28 @@ ResilientEnumTestSuite.test("ResilientEnumExtension") {
436436
expectEqual(Base.self, ResilientMultiPayloadGenericEnumFixedSize<Base>.A.getTypeParameter())
437437
}
438438

439+
public class Container {
440+
private enum Multi {
441+
case none
442+
case some(Container)
443+
case other(ResilientRef)
444+
}
445+
private var m: Multi
446+
var i: Int
447+
init() {
448+
m = .none
449+
i = 0
450+
switch self.m {
451+
case .none:
452+
print("success")
453+
case .some(_), .other(_):
454+
assert(false, "noooo!")
455+
}
456+
}
457+
}
458+
459+
ResilientEnumTestSuite.test("ResilientPrivateEnumMember") {
460+
_ = Container()
461+
}
462+
439463
runAllTests()

0 commit comments

Comments
 (0)