Skip to content

Commit 1e8a0ba

Browse files
committed
(Mostly) revert "SILGen: TupleShuffleExprs in the rvalue emission path can't have scalar-to-tuple or tuple-to-scalar"
We use TupleShuffleExpr in RValue position for enum element payloads, and it can happen that the source is a scalar if you're calling the enum element constructor with a trailing closure. This reverts commit 7960660. Fixes <https://bugs.swift.org/browse/SR-9675>.
1 parent d35018b commit 1e8a0ba

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2285,9 +2285,13 @@ static void emitTupleShuffleExprInto(RValueEmitter &emitter,
22852285
// Map outer initializations into a tuple of inner initializations:
22862286
// - fill out the initialization elements with null
22872287
TupleInitialization innerTupleInit;
2288-
CanTupleType innerTuple =
2289-
cast<TupleType>(E->getSubExpr()->getType()->getCanonicalType());
2290-
innerTupleInit.SubInitializations.resize(innerTuple->getNumElements());
2288+
if (E->isSourceScalar()) {
2289+
innerTupleInit.SubInitializations.push_back(nullptr);
2290+
} else {
2291+
CanTupleType innerTuple =
2292+
cast<TupleType>(E->getSubExpr()->getType()->getCanonicalType());
2293+
innerTupleInit.SubInitializations.resize(innerTuple->getNumElements());
2294+
}
22912295

22922296
// Map all the outer initializations to their appropriate targets.
22932297
for (unsigned outerIndex = 0; outerIndex != outerInits.size(); outerIndex++) {
@@ -2305,14 +2309,20 @@ static void emitTupleShuffleExprInto(RValueEmitter &emitter,
23052309
#endif
23062310

23072311
// Emit the sub-expression into the tuple initialization we just built.
2308-
emitter.SGF.emitExprInto(E->getSubExpr(), &innerTupleInit);
2312+
if (E->isSourceScalar()) {
2313+
emitter.SGF.emitExprInto(E->getSubExpr(),
2314+
innerTupleInit.SubInitializations[0].get());
2315+
} else {
2316+
emitter.SGF.emitExprInto(E->getSubExpr(), &innerTupleInit);
2317+
}
23092318

23102319
outerTupleInit->finishInitialization(emitter.SGF);
23112320
}
23122321

23132322
RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E,
23142323
SGFContext C) {
2315-
assert(!E->isSourceScalar());
2324+
// FIXME: Once we're no longer using this code path for enum element payloads,
2325+
// also assert that !E->isSourceScalar().
23162326
assert(!E->isResultScalar());
23172327

23182328
// If we're emitting into an initialization, we can try shuffling the
@@ -2326,7 +2336,11 @@ RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E,
23262336

23272337
// Emit the sub-expression tuple and destructure it into elements.
23282338
SmallVector<RValue, 4> elements;
2329-
visit(E->getSubExpr()).extractElements(elements);
2339+
if (E->isSourceScalar()) {
2340+
elements.push_back(visit(E->getSubExpr()));
2341+
} else {
2342+
visit(E->getSubExpr()).extractElements(elements);
2343+
}
23302344

23312345
// Prepare a new tuple to hold the shuffled result.
23322346
RValue result(E->getType()->getCanonicalType());

test/SILGen/enum.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,33 @@ enum Indirect<T> {
203203
func makeIndirectEnum<T>(_ payload: T) -> Indirect<T> {
204204
return Indirect.payload((payload, other: payload))
205205
}
206+
207+
// https://bugs.swift.org/browse/SR-9675
208+
209+
enum TrailingClosureConcrete {
210+
case label(fn: () -> Int)
211+
case noLabel(() -> Int)
212+
case twoElementsLabel(x: Int, fn: () -> Int)
213+
case twoElementsNoLabel(_ x: Int, _ fn: () -> Int)
214+
}
215+
216+
func useTrailingClosureConcrete() {
217+
_ = TrailingClosureConcrete.label { 0 }
218+
_ = TrailingClosureConcrete.noLabel { 0 }
219+
_ = TrailingClosureConcrete.twoElementsLabel(x: 0) { 0 }
220+
_ = TrailingClosureConcrete.twoElementsNoLabel(0) { 0 }
221+
}
222+
223+
enum TrailingClosureGeneric<T> {
224+
case label(fn: () -> T)
225+
case noLabel(() -> T)
226+
case twoElementsLabel(x: T, fn: () -> T)
227+
case twoElementsNoLabel(_ x: T, _ fn: () -> T)
228+
}
229+
230+
func useTrailingClosureGeneric<T>(t: T) {
231+
_ = TrailingClosureGeneric<T>.label { t }
232+
_ = TrailingClosureGeneric<T>.noLabel { t }
233+
_ = TrailingClosureGeneric<T>.twoElementsLabel(x: t) { t }
234+
_ = TrailingClosureGeneric<T>.twoElementsNoLabel(t) { t }
235+
}

0 commit comments

Comments
 (0)