Skip to content

Commit 7a16b02

Browse files
committed
AST: Allow one-element tuple types to be constructed
These will never appear in the source language, but can arise after substitution when the original type is a tuple type with a pack expansion type. Two examples: - original type: (Int, T...), substitution T := {} - original type: (T...), substitution T := {Int} We need to model these correctly to maintain invariants. Callers that previously used to rely on TupleType::get() returning a ParenType now explicitly check for the one-element case instead.
1 parent ae37591 commit 7a16b02

File tree

16 files changed

+64
-47
lines changed

16 files changed

+64
-47
lines changed

include/swift/AST/Pattern.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,6 @@ class ParenPattern : public Pattern {
260260
///
261261
/// The fully general form of this is something like:
262262
/// label: (pattern) = initexpr
263-
///
264-
/// The Init and DefArgKind fields are only used in argument lists for
265-
/// functions. They are not parsed as part of normal pattern grammar.
266263
class TuplePatternElt {
267264
Identifier Label;
268265
SourceLoc LabelLoc;
@@ -277,10 +274,6 @@ class TuplePatternElt {
277274

278275
Identifier getLabel() const { return Label; }
279276
SourceLoc getLabelLoc() const { return LabelLoc; }
280-
void setLabel(Identifier I, SourceLoc Loc) {
281-
Label = I;
282-
LabelLoc = Loc;
283-
}
284277

285278
Pattern *getPattern() { return ThePattern; }
286279
const Pattern *getPattern() const {

include/swift/AST/Types.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,10 +2270,11 @@ class TupleType final : public TypeBase, public llvm::FoldingSetNode,
22702270

22712271
public:
22722272
/// get - Return the uniqued tuple type with the specified elements.
2273-
/// Returns a ParenType instead if there is exactly one element which
2274-
/// is unlabeled and not varargs, so it doesn't accidentally construct
2275-
/// a tuple which is impossible to write.
2276-
static Type get(ArrayRef<TupleTypeElt> Elements, const ASTContext &C);
2273+
///
2274+
/// This can construct one-element tuple types, which are impossible to
2275+
/// write in the source language. The caller should check for that case
2276+
/// first it a bona fide 'r-value' type is desired.
2277+
static TupleType *get(ArrayRef<TupleTypeElt> Elements, const ASTContext &C);
22772278

22782279
/// getEmpty - Return the empty tuple type '()'.
22792280
static CanTypeWrapper<TupleType> getEmpty(const ASTContext &C);

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2853,10 +2853,7 @@ void TupleType::Profile(llvm::FoldingSetNodeID &ID,
28532853
}
28542854

28552855
/// getTupleType - Return the uniqued tuple type with the specified elements.
2856-
Type TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
2857-
if (Fields.size() == 1 && !Fields[0].hasName())
2858-
return ParenType::get(C, Fields[0].getType());
2859-
2856+
TupleType *TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
28602857
RecursiveTypeProperties properties;
28612858
for (const TupleTypeElt &Elt : Fields) {
28622859
auto eltTy = Elt.getType();
@@ -3608,6 +3605,8 @@ Type AnyFunctionType::composeTuple(ASTContext &ctx, ArrayRef<Param> params,
36083605
}
36093606
elements.emplace_back(param.getParameterType(), param.getLabel());
36103607
}
3608+
if (elements.size() == 1 && !elements[0].hasName())
3609+
return ParenType::get(ctx, elements[0].getType());
36113610
return TupleType::get(elements, ctx);
36123611
}
36133612

lib/AST/Pattern.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ Identifier NamedPattern::getBoundName() const {
372372
TuplePattern *TuplePattern::create(ASTContext &C, SourceLoc lp,
373373
ArrayRef<TuplePatternElt> elts,
374374
SourceLoc rp) {
375+
#ifndef NDEBUG
376+
if (elts.size() == 1)
377+
assert(!elts[0].getLabel().empty());
378+
#endif
379+
375380
unsigned n = elts.size();
376381
void *buffer = C.Allocate(totalSizeToAlloc<TuplePatternElt>(n),
377382
alignof(TuplePattern));
@@ -387,7 +392,7 @@ Pattern *TuplePattern::createSimple(ASTContext &C, SourceLoc lp,
387392
assert(lp.isValid() == rp.isValid());
388393

389394
if (elements.size() == 1 &&
390-
elements[0].getPattern()->getBoundName().empty()) {
395+
elements[0].getLabel().empty()) {
391396
auto &first = const_cast<TuplePatternElt&>(elements.front());
392397
return new (C) ParenPattern(lp, first.getPattern(), rp);
393398
}

lib/AST/Type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6255,7 +6255,7 @@ TypeBase::getAutoDiffTangentSpace(LookupConformanceFn lookupConformance) {
62556255
TangentSpace::getTuple(ctx.TheEmptyTupleType->castTo<TupleType>()));
62566256
if (newElts.size() == 1)
62576257
return cache(TangentSpace::getTangentVector(newElts.front().getType()));
6258-
auto *tupleType = TupleType::get(newElts, ctx)->castTo<TupleType>();
6258+
auto *tupleType = TupleType::get(newElts, ctx);
62596259
return cache(TangentSpace::getTuple(tupleType));
62606260
}
62616261

lib/ClangImporter/ImportType.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,9 @@ namespace {
619619
if (size > 4096)
620620
return Type();
621621

622+
if (size == 1)
623+
return ParenType::get(elementType->getASTContext(), elementType);
624+
622625
SmallVector<TupleTypeElt, 8> elts{static_cast<size_t>(size), elementType};
623626
return TupleType::get(elts, elementType->getASTContext());
624627
}

lib/IRGen/MetadataRequest.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3197,10 +3197,7 @@ class EmitTypeMetadataRefForLayout
31973197
if (!changed)
31983198
return ty;
31993199

3200-
// The cast should succeed, because if we end up with a one-element
3201-
// tuple type here, it must have a label.
3202-
return cast<TupleType>(
3203-
CanType(TupleType::get(loweredElts, ty->getASTContext())));
3200+
return CanTupleType(TupleType::get(loweredElts, ty->getASTContext()));
32043201
}
32053202

32063203
CanType visitAnyFunctionType(CanAnyFunctionType ty) {

lib/SILGen/SILGenExpr.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3165,12 +3165,12 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
31653165

31663166
static void
31673167
getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM,
3168-
SILLocation loc,
3169-
GenericEnvironment *genericEnv,
3170-
ResilienceExpansion expansion,
3171-
ArrayRef<KeyPathPatternComponent::Index> indexes,
3172-
SILFunction *&equals,
3173-
SILFunction *&hash) {
3168+
SILLocation loc,
3169+
GenericEnvironment *genericEnv,
3170+
ResilienceExpansion expansion,
3171+
ArrayRef<KeyPathPatternComponent::Index> indexes,
3172+
SILFunction *&equals,
3173+
SILFunction *&hash) {
31743174
if (indexes.empty()) {
31753175
equals = nullptr;
31763176
hash = nullptr;
@@ -3198,14 +3198,21 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM,
31983198
for (auto &index : indexes)
31993199
indexTypes.push_back(index.FormalType);
32003200

3201-
SmallVector<TupleTypeElt, 2> indexElts;
3202-
for (auto &elt : indexes) {
3203-
indexElts.push_back(GenericEnvironment::mapTypeIntoContext(genericEnv,
3204-
elt.FormalType));
3201+
CanType indexTupleTy;
3202+
if (indexes.size() == 1) {
3203+
indexTupleTy = GenericEnvironment::mapTypeIntoContext(
3204+
genericEnv, indexes[0].FormalType)->getCanonicalType();
3205+
} else {
3206+
SmallVector<TupleTypeElt, 2> indexElts;
3207+
for (auto &elt : indexes) {
3208+
indexElts.push_back(GenericEnvironment::mapTypeIntoContext(
3209+
genericEnv, elt.FormalType));
3210+
}
3211+
3212+
indexTupleTy = TupleType::get(indexElts, SGM.getASTContext())
3213+
->getCanonicalType();
32053214
}
32063215

3207-
auto indexTupleTy = TupleType::get(indexElts, SGM.getASTContext())
3208-
->getCanonicalType();
32093216
RValue indexValue(indexTupleTy);
32103217

32113218
auto indexLoweredTy =

lib/SILGen/SILGenPoly.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,8 @@ namespace {
934934
assert(!param.isInOut());
935935
elts.emplace_back(param.getParameterType());
936936
}
937-
auto outputSubstType = cast<TupleType>(
938-
TupleType::get(elts, SGF.getASTContext())
939-
->getCanonicalType());
937+
auto outputSubstType = CanTupleType(
938+
TupleType::get(elts, SGF.getASTContext()));
940939

941940
// Translate the input tuple value into the output tuple value. Note
942941
// that the output abstraction pattern is a tuple, and we explode tuples

lib/SILOptimizer/Transforms/PartialApplySimplification.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,11 +485,17 @@ rewriteKnownCalleeWithExplicitContext(SILFunction *callee,
485485
// TODO: SILBoxType is only implemented for a single field right now, and we
486486
// don't yet have a corresponding type for nonescaping captures, so
487487
// represent the captures as a tuple for now.
488-
llvm::SmallVector<TupleTypeElt, 4> tupleElts;
489-
for (auto field : boxFields) {
490-
tupleElts.push_back(TupleTypeElt(field.getLoweredType()));
488+
CanType tupleTy;
489+
490+
if (boxFields.size() == 1) {
491+
tupleTy = boxFields[0].getLoweredType();
492+
} else {
493+
llvm::SmallVector<TupleTypeElt, 4> tupleElts;
494+
for (auto field : boxFields) {
495+
tupleElts.push_back(TupleTypeElt(field.getLoweredType()));
496+
}
497+
tupleTy = TupleType::get(tupleElts, C)->getCanonicalType();
491498
}
492-
auto tupleTy = TupleType::get(tupleElts, C)->getCanonicalType();
493499

494500
CanType contextTy;
495501
SILParameterInfo contextParam;

0 commit comments

Comments
 (0)