Skip to content

Commit 3faee07

Browse files
committed
Teach RValue to not recursively expand tuples with pack expansions
Arguably, it would be more consistent with the current design to figure out a representation for pack-expansion components so that we can keep them around in whatever storage. But honestly, I don't like the current design; I think the eager explosion is an over-complicated mistake. So this is partly just me finding an excuse to not extend that to more cases.
1 parent b0dd825 commit 3faee07

File tree

1 file changed

+42
-8
lines changed

1 file changed

+42
-8
lines changed

lib/SILGen/RValue.cpp

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ static unsigned getTupleSize(CanType t) {
4242

4343
unsigned RValue::getRValueSize(AbstractionPattern pattern, CanType formalType) {
4444
if (pattern.isTuple()) {
45+
if (pattern.doesTupleContainPackExpansionType())
46+
return 1;
47+
48+
// We can use the naive parallel walk here because of the check above.
4549
unsigned count = 0;
4650
auto formalTupleType = cast<TupleType>(formalType);
4751
for (auto i : indices(formalTupleType.getElementTypes())) {
@@ -57,6 +61,10 @@ unsigned RValue::getRValueSize(AbstractionPattern pattern, CanType formalType) {
5761
/// Return the number of rvalue elements in the given canonical type.
5862
unsigned RValue::getRValueSize(CanType type) {
5963
if (auto tupleType = dyn_cast<TupleType>(type)) {
64+
// Don't recursively expand tuples containing pack expansions.
65+
if (tupleType.containsPackExpansionType())
66+
return 1;
67+
6068
unsigned count = 0;
6169
for (auto eltType : tupleType.getElementTypes())
6270
count += getRValueSize(eltType);
@@ -156,6 +164,10 @@ class ExplodeTupleValue
156164
}
157165

158166
void visitTupleType(CanTupleType tupleFormalType, ManagedValue tuple) {
167+
// Don't recursively expand tuples containing pack expansions.
168+
if (tupleFormalType.containsPackExpansionType())
169+
return visitType(tupleFormalType, tuple);
170+
159171
if (tuple.getType().isObject()) {
160172
return visitObjectTupleType(tupleFormalType, tuple);
161173
}
@@ -202,6 +214,10 @@ class ImplodeLoadableTupleValue
202214
}
203215

204216
ManagedValue visitTupleType(CanTupleType t, SILLocation l) {
217+
// Tuples with pack expansions aren't exploded.
218+
if (t.containsPackExpansionType())
219+
return visitType(t, l);
220+
205221
SmallVector<ManagedValue, 4> elts;
206222
for (auto fieldTy : t.getElementTypes())
207223
elts.push_back(this->visit(fieldTy, l));
@@ -251,6 +267,10 @@ class ImplodeAddressOnlyTuple
251267
}
252268

253269
void visitTupleType(CanTupleType t, Initialization *address, SILLocation l) {
270+
// Tuples containing pack expansions shouldn't be exploded.
271+
if (t.containsPackExpansionType())
272+
return visitType(t, address, l);
273+
254274
assert(address->canSplitIntoTupleElements());
255275
llvm::SmallVector<InitializationPtr, 4> buf;
256276
auto bufResult = address->splitIntoTupleElements(SGF, l, t, buf);
@@ -272,10 +292,11 @@ class ImplodeAddressOnlyTuple
272292

273293
template <ImplodeKind KIND>
274294
static ManagedValue implodeTupleValues(ArrayRef<ManagedValue> values,
275-
SILGenFunction &SGF, CanType tupleType,
295+
SILGenFunction &SGF, CanType type,
276296
SILLocation l) {
277297
// Non-tuples don't need to be imploded.
278-
if (!isa<TupleType>(tupleType)) {
298+
auto tupleType = dyn_cast<TupleType>(type);
299+
if (!tupleType || tupleType.containsPackExpansionType()) {
279300
assert(values.size() == 1 && "exploded non-tuple value?!");
280301
return ImplodeLoadableTupleValue<KIND>::getValue(SGF, values[0], l);
281302
}
@@ -289,13 +310,13 @@ static ManagedValue implodeTupleValues(ArrayRef<ManagedValue> values,
289310
"address-only values are always managed!");
290311
auto buffer = SGF.emitTemporary(l, TL);
291312
ImplodeAddressOnlyTuple<KIND>(values, SGF)
292-
.visit(tupleType, buffer.get(), l);
313+
.visitTupleType(tupleType, buffer.get(), l);
293314
return buffer->getManagedAddress();
294315
}
295316

296317
// To implode loadable tuples, we just need to combine the elements with
297318
// TupleInsts.
298-
return ImplodeLoadableTupleValue<KIND>(values, SGF).visit(tupleType, l);
319+
return ImplodeLoadableTupleValue<KIND>(values, SGF).visitTupleType(tupleType, l);
299320
}
300321

301322
/// Perform a copy or init operation from an array of ManagedValue (from an
@@ -321,7 +342,7 @@ static void copyOrInitValuesInto(Initialization *init,
321342

322343
// If the element has non-tuple type, just serve it up to the initialization.
323344
auto tupleType = dyn_cast<TupleType>(type);
324-
if (!tupleType) {
345+
if (!tupleType || tupleType.containsPackExpansionType()) {
325346
// We take the first value.
326347
ManagedValue result = values[0];
327348
values = values.slice(1);
@@ -373,7 +394,7 @@ LLVM_ATTRIBUTE_UNUSED
373394
static unsigned
374395
expectedExplosionSize(CanType type) {
375396
auto tuple = dyn_cast<TupleType>(type);
376-
if (!tuple)
397+
if (!tuple || tuple.containsPackExpansionType())
377398
return 1;
378399
unsigned total = 0;
379400
for (unsigned i = 0; i < tuple->getNumElements(); ++i) {
@@ -545,7 +566,8 @@ static void assignRecursive(SILGenFunction &SGF, SILLocation loc,
545566
CanType type, ArrayRef<ManagedValue> &srcValues,
546567
SILValue destAddr) {
547568
// Recurse into tuples.
548-
if (auto srcTupleType = dyn_cast<TupleType>(type)) {
569+
auto srcTupleType = dyn_cast<TupleType>(type);
570+
if (srcTupleType && !srcTupleType.containsPackExpansionType()) {
549571
assert(destAddr->getType().castTo<TupleType>()->getNumElements()
550572
== srcTupleType->getNumElements());
551573
for (auto eltIndex : indices(srcTupleType.getElementTypes())) {
@@ -651,10 +673,16 @@ RValue RValue::extractElement(unsigned n) && {
651673
return element;
652674
}
653675

676+
// This is implementable, but we can do it lazily if we add that kind
677+
// of projection.
678+
assert(!tupleTy.containsPackExpansionType() &&
679+
"can't extract elements from tuples containing pack expansions "
680+
"right now");
681+
654682
auto range = getElementRange(tupleTy, n);
655683
unsigned from = range.first, to = range.second;
656684

657-
CanType eltType = cast<TupleType>(type).getElementType(n);
685+
CanType eltType = tupleTy.getElementType(n);
658686
RValue element(nullptr, llvm::makeArrayRef(values).slice(from, to - from), eltType);
659687
makeUsed();
660688
return element;
@@ -674,6 +702,12 @@ void RValue::extractElements(SmallVectorImpl<RValue> &elements) && {
674702
return;
675703
}
676704

705+
// This is implementable, but we can do it lazily if we add that kind
706+
// of decomposition.
707+
assert(!tupleTy.containsPackExpansionType() &&
708+
"can't extract elements from tuples containing pack expansions "
709+
"right now");
710+
677711
unsigned from = 0;
678712
for (auto eltType : tupleTy.getElementTypes()) {
679713
unsigned to = from + getRValueSize(eltType);

0 commit comments

Comments
 (0)