Skip to content

Commit 2a44e1b

Browse files
authored
Merge pull request swiftlang#23246 from gottesmm/pr-6d1fd5941d66a83ef30129d5cc79f79db52cb578
2 parents d7b919c + 85ee550 commit 2a44e1b

File tree

2 files changed

+43
-24
lines changed

2 files changed

+43
-24
lines changed

lib/SILGen/SILGenPattern.cpp

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,37 +1868,44 @@ void PatternMatchEmission::emitEnumElementObjectDispatch(
18681868
// instruction to receive the enum case data if it has any.
18691869

18701870
SILType eltTy;
1871-
bool hasElt = false;
1872-
if (elt->hasAssociatedValues()) {
1871+
bool hasNonVoidAssocValue = false;
1872+
bool hasAssocValue = elt->hasAssociatedValues();
1873+
if (hasAssocValue) {
18731874
eltTy = src.getType().getEnumElementType(elt, SGF.SGM.M);
1874-
hasElt = !eltTy.getASTType()->isVoid();
1875+
hasNonVoidAssocValue = !eltTy.getASTType()->isVoid();
18751876
}
18761877

18771878
ConsumableManagedValue eltCMV, origCMV;
18781879

1879-
// Empty cases. Try to avoid making an empty tuple value if it's
1880-
// obviously going to be ignored. This assumes that we won't even
1881-
// try to touch the value in such cases, although we may touch the
1882-
// cleanup (enough to see that it's not present).
1883-
if (!hasElt) {
1884-
bool hasNonAny = false;
1885-
for (auto &specRow : specializedRows) {
1886-
auto pattern = specRow.Patterns[0];
1887-
if (pattern &&
1888-
!isa<AnyPattern>(pattern->getSemanticsProvidingPattern())) {
1889-
hasNonAny = true;
1890-
break;
1880+
// Void (i.e. empty) cases.
1881+
//
1882+
if (!hasNonVoidAssocValue) {
1883+
// Inline constructor.
1884+
eltCMV = [&]() -> ConsumableManagedValue {
1885+
// If we have an associated value, rather than no payload at all, we
1886+
// still need to create the argument. So do that instead of creating the
1887+
// empty-tuple. Otherwise, we need to create undef or the empty-tuple.
1888+
if (hasAssocValue) {
1889+
return {SGF.B.createOwnedPhiArgument(eltTy),
1890+
CastConsumptionKind::TakeAlways};
18911891
}
1892-
}
18931892

1894-
SILValue result;
1895-
if (hasNonAny) {
1896-
result = SGF.emitEmptyTuple(loc);
1897-
} else {
1898-
result = SILUndef::get(SGF.SGM.Types.getEmptyTupleType(), SGF.F);
1899-
}
1900-
origCMV = ConsumableManagedValue::forUnmanaged(result);
1901-
eltCMV = origCMV;
1893+
// Otherwise, try to avoid making an empty tuple value if it's obviously
1894+
// going to be ignored. This assumes that we won't even try to touch the
1895+
// value in such cases, although we may touch the cleanup (enough to see
1896+
// that it's not present).
1897+
bool hasNonAny =
1898+
llvm::any_of(specializedRows, [&](const SpecializedRow &row) {
1899+
auto *p = row.Patterns[0];
1900+
return p && !isa<AnyPattern>(p->getSemanticsProvidingPattern());
1901+
});
1902+
if (hasNonAny) {
1903+
return ConsumableManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
1904+
}
1905+
1906+
return ConsumableManagedValue::forUnmanaged(
1907+
SILUndef::get(SGF.SGM.Types.getEmptyTupleType(), SGF.F));
1908+
}();
19021909

19031910
// Okay, specialize on the argument.
19041911
} else {

test/SILGen/switch.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,3 +1291,15 @@ indirect enum SR6664_Base<Element> {
12911291
}
12921292
}
12931293
}
1294+
1295+
// Make sure that we properly create switch_enum success arguments if we have an
1296+
// associated type that is a void type.
1297+
func testVoidType() {
1298+
let x: Optional<()> = ()
1299+
switch x {
1300+
case .some(let x):
1301+
break
1302+
case .none:
1303+
break
1304+
}
1305+
}

0 commit comments

Comments
 (0)