Skip to content

Commit d836766

Browse files
authored
Merge pull request #66382 from slavapestov/pack-element-type-5.9
Preliminary support for pack element references to outer pack expansions [5.9]
2 parents bfdec5c + 0e754a0 commit d836766

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2117
-1380
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,8 @@ Types
675675
type ::= assoc-type-list 'QZ' // shortcut for 'QYz'
676676
type ::= opaque-type-decl-name bound-generic-args 'Qo' INDEX // opaque type
677677
678+
type ::= pack-type 'Qe' INDEX // pack element type
679+
678680
type ::= pattern-type count-type 'Qp' // pack expansion type
679681
type ::= pack-element-list 'QP' // pack type
680682
type ::= pack-element-list 'QS' DIRECTNESS // SIL pack type

include/swift/AST/InFlightSubstitution.h

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,27 +49,15 @@ class InFlightSubstitution {
4949
InFlightSubstitution(const InFlightSubstitution &) = delete;
5050
InFlightSubstitution &operator=(const InFlightSubstitution &) = delete;
5151

52-
// TODO: when we add PackElementType, we should recognize it during
53-
// substitution and either call different methods on this class or
54-
// pass an extra argument for the pack-expansion depth D. We should
55-
// be able to rely on that to mark a pack-element reference instead
56-
// of checking whether the original type was a pack. Substitution
57-
// should use the D'th entry from the end of ActivePackExpansions to
58-
// guide the element substitution:
59-
// - project the given index of the pack substitution
60-
// - wrap it in a PackElementType if it's a subst expansion
61-
// - the depth of that PackElementType is the number of subst
62-
// expansions between the depth entry and the end of
63-
// ActivePackExpansions
64-
6552
/// Perform primitive substitution on the given type. Returns Type()
6653
/// if the type should not be substituted as a whole.
67-
Type substType(SubstitutableType *origType);
54+
Type substType(SubstitutableType *origType, unsigned level);
6855

6956
/// Perform primitive conformance lookup on the given type.
7057
ProtocolConformanceRef lookupConformance(CanType dependentType,
7158
Type conformingReplacementType,
72-
ProtocolDecl *conformedProtocol);
59+
ProtocolDecl *conformedProtocol,
60+
unsigned level);
7361

7462
/// Given the shape type of a pack expansion, invoke the given callback
7563
/// for each expanded component of it. If the substituted component

include/swift/AST/Type.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,11 @@ enum class SubstFlags {
151151
/// Map member types to their desugared witness type.
152152
DesugarMemberTypes = 0x02,
153153
/// Substitute types involving opaque type archetypes.
154-
SubstituteOpaqueArchetypes = 0x04
154+
SubstituteOpaqueArchetypes = 0x04,
155+
/// Don't increase pack expansion level for free pack references.
156+
/// Do not introduce new usages of this flag.
157+
/// FIXME: Remove this.
158+
PreservePackExpansionLevel = 0x08,
155159
};
156160

157161
/// Options for performing substitutions into a type.

include/swift/AST/TypeDifferenceVisitor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor<Impl, bool> {
149149
return asImpl().visit(type1.getPatternType(), type2.getPatternType());
150150
}
151151

152+
bool visitPackElementType(CanPackElementType type1,
153+
CanPackElementType type2) {
154+
return asImpl().visit(type1.getPackType(), type2.getPackType());
155+
}
156+
152157
bool visitTupleType(CanTupleType type1, CanTupleType type2) {
153158
return visitComponentArray(type1, type2,
154159
type1->getElements(), type2->getElements());

include/swift/AST/TypeMatcher.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,18 @@ class TypeMatcher {
202202
return mismatch(firstPE.getPointer(), secondType, sugaredFirstType);
203203
}
204204

205+
bool visitPackElementType(CanPackElementType firstElement, Type secondType,
206+
Type sugaredFirstType) {
207+
if (auto secondElement = secondType->getAs<PackElementType>()) {
208+
return this->visit(firstElement.getPackType(),
209+
secondElement->getPackType(),
210+
sugaredFirstType->castTo<PackElementType>()
211+
->getPackType());
212+
}
213+
214+
return mismatch(firstElement.getPointer(), secondType, sugaredFirstType);
215+
}
216+
205217
bool visitReferenceStorageType(CanReferenceStorageType firstStorage,
206218
Type secondType, Type sugaredFirstType) {
207219
if (firstStorage->getKind() == secondType->getDesugaredType()->getKind()) {

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ TYPE(LValue, Type)
186186
TYPE(InOut, Type)
187187
TYPE(Pack, Type)
188188
TYPE(PackExpansion, Type)
189+
TYPE(PackElement, Type)
189190
UNCHECKED_TYPE(TypeVariable, Type)
190191
ABSTRACT_SUGARED_TYPE(Sugar, Type)
191192
SUGARED_TYPE(Paren, SugarType)

include/swift/AST/Types.h

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -710,8 +710,10 @@ class alignas(1 << TypeAlignInBits) TypeBase
710710
SmallVectorImpl<OpenedArchetypeType *> &rootOpenedArchetypes) const;
711711

712712
/// Retrieve the set of type parameter packs that occur within this type.
713-
void getTypeParameterPacks(
714-
SmallVectorImpl<Type> &rootParameterPacks);
713+
void getTypeParameterPacks(SmallVectorImpl<Type> &rootParameterPacks);
714+
715+
/// Retrieve the set of type parameter packs that occur within this type.
716+
void walkPackReferences(llvm::function_ref<bool (Type)> fn);
715717

716718
/// Replace opened archetypes with the given root with their most
717719
/// specific non-dependent upper bounds throughout this type.
@@ -778,6 +780,9 @@ class alignas(1 << TypeAlignInBits) TypeBase
778780
/// this function will wrap into a pack containing a singleton expansion.
779781
PackType *getPackSubstitutionAsPackType();
780782

783+
/// Increase the expansion level of each parameter pack appearing in this type.
784+
Type increasePackElementLevel(unsigned level);
785+
781786
/// Determines whether this type is an lvalue. This includes both straight
782787
/// lvalue types as well as tuples or optionals of lvalues.
783788
bool hasLValueType() {
@@ -6412,7 +6417,7 @@ class PackArchetypeType final
64126417
LayoutConstraint Layout);
64136418

64146419
// Returns the reduced shape type for this pack archetype.
6415-
CanType getReducedShape() const;
6420+
CanType getReducedShape();
64166421

64176422
static bool classof(const TypeBase *T) {
64186423
return T->getKind() == TypeKind::PackArchetype;
@@ -6994,13 +6999,71 @@ BEGIN_CAN_TYPE_WRAPPER(PackExpansionType, Type)
69946999
}
69957000
END_CAN_TYPE_WRAPPER(PackExpansionType, Type)
69967001

6997-
69987002
inline CanTypeWrapper<PackExpansionType>
69997003
CanPackType::unwrapSingletonPackExpansion() const {
70007004
return CanPackExpansionType(
70017005
getPointer()->unwrapSingletonPackExpansion());
70027006
}
70037007

7008+
/// Represents a reference to a pack from an outer expansion. This comes up
7009+
/// after substitution. For example, given these declarations:
7010+
///
7011+
/// typealias A<each T, U> = (repeat (each T, U))
7012+
/// typealias B<each X, repeat each Y> = (repeat A<repeat each X, each Y>)
7013+
///
7014+
/// Naively substituting replacing {T := repeat each X, U := each Y} in the
7015+
/// underlying type of A would give us:
7016+
///
7017+
/// '(repeat (repeat (each X, each Y)))'
7018+
///
7019+
/// However, this is wrong; we're not expanding X and Y in parallel (they
7020+
/// might not even have the same shape). Instead, we're expanding X, and
7021+
/// then on each iteration, expanding Y.
7022+
///
7023+
/// If we annotate each 'repeat' and its corresponding 'each', we instead see
7024+
/// that the above should give us:
7025+
///
7026+
/// '(repeat[1] (repeat[0] (each[0], each[1] U)))'
7027+
///
7028+
/// We number PackExpansionTypes from the innermost one outwards, assigning
7029+
/// a level of 0 to the innermost one. Then, a PackElementType represents a
7030+
/// reference to a parameter pack from an expansion with level > 0.
7031+
class PackElementType : public TypeBase, public llvm::FoldingSetNode {
7032+
friend class ASTContext;
7033+
7034+
Type packType;
7035+
unsigned level;
7036+
7037+
PackElementType(Type packType, unsigned level,
7038+
RecursiveTypeProperties properties,
7039+
const ASTContext *ctx);
7040+
7041+
public:
7042+
static PackElementType *get(Type packType, unsigned level);
7043+
7044+
Type getPackType() const { return packType; }
7045+
7046+
unsigned getLevel() const { return level; }
7047+
7048+
void Profile(llvm::FoldingSetNodeID &ID) {
7049+
Profile(ID, getPackType(), getLevel());
7050+
}
7051+
7052+
static void Profile(llvm::FoldingSetNodeID &ID, Type packType, unsigned level);
7053+
7054+
// Implement isa/cast/dyncast/etc.
7055+
static bool classof(const TypeBase *T) {
7056+
return T->getKind() == TypeKind::PackElement;
7057+
}
7058+
};
7059+
BEGIN_CAN_TYPE_WRAPPER(PackElementType, Type)
7060+
static CanPackElementType get(CanType pack);
7061+
7062+
CanType getPackType() const {
7063+
return CanType(getPointer()->getPackType());
7064+
}
7065+
END_CAN_TYPE_WRAPPER(PackElementType, Type)
7066+
70047067
/// getASTContext - Return the ASTContext that this type belongs to.
70057068
inline ASTContext &TypeBase::getASTContext() const {
70067069
// If this type is canonical, it has the ASTContext in it.
@@ -7035,16 +7098,6 @@ inline bool TypeBase::isTypeParameter() {
70357098
return t->is<GenericTypeParamType>();
70367099
}
70377100

7038-
inline bool TypeBase::isParameterPack() {
7039-
Type t(this);
7040-
7041-
while (auto *memberTy = t->getAs<DependentMemberType>())
7042-
t = memberTy->getBase();
7043-
7044-
return t->is<GenericTypeParamType>() &&
7045-
t->castTo<GenericTypeParamType>()->isParameterPack();
7046-
}
7047-
70487101
// TODO: This will become redundant once InOutType is removed.
70497102
inline bool TypeBase::isMaterializable() {
70507103
return !(hasLValueType() || is<InOutType>());

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ NODE(Pack)
241241
NODE(SILPackDirect)
242242
NODE(SILPackIndirect)
243243
NODE(PackExpansion)
244+
NODE(PackElement)
245+
NODE(PackElementLevel)
244246
NODE(Type)
245247
CONTEXT_NODE(TypeSymbolicReference)
246248
CONTEXT_NODE(TypeAlias)

include/swift/SIL/AbstractionPattern.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -938,10 +938,9 @@ class AbstractionPattern {
938938
case Kind::Discard: {
939939
auto type = getType();
940940
if (isa<DependentMemberType>(type) ||
941-
isa<GenericTypeParamType>(type)) {
942-
return true;
943-
}
944-
if (isa<ArchetypeType>(type)) {
941+
isa<GenericTypeParamType>(type) ||
942+
isa<PackElementType>(type) ||
943+
isa<ArchetypeType>(type)) {
945944
return true;
946945
}
947946
return false;
@@ -960,7 +959,8 @@ class AbstractionPattern {
960959
case Kind::Discard: {
961960
auto type = getType();
962961
if (isa<DependentMemberType>(type) ||
963-
isa<GenericTypeParamType>(type)) {
962+
isa<GenericTypeParamType>(type) ||
963+
isa<PackElementType>(type)) {
964964
return true;
965965
}
966966
if (auto archetype = dyn_cast<ArchetypeType>(type)) {
@@ -1448,6 +1448,10 @@ class AbstractionPattern {
14481448
/// the abstraction pattern for an element type.
14491449
AbstractionPattern getTupleElementType(unsigned index) const;
14501450

1451+
/// Given that the value being abstracted is a pack element type, return
1452+
/// the abstraction pattern for its pack type.
1453+
AbstractionPattern getPackElementPackType() const;
1454+
14511455
/// Given that the value being abstracted is a pack type, return
14521456
/// the abstraction pattern for an element type.
14531457
AbstractionPattern getPackElementType(unsigned index) const;

include/swift/SIL/SILType.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,12 +660,12 @@ class SILType {
660660
SILType subst(Lowering::TypeConverter &tc, TypeSubstitutionFn subs,
661661
LookupConformanceFn conformances,
662662
CanGenericSignature genericSig = CanGenericSignature(),
663-
bool shouldSubstituteOpaqueArchetypes = false) const;
663+
SubstOptions options = None) const;
664664

665665
SILType subst(SILModule &M, TypeSubstitutionFn subs,
666666
LookupConformanceFn conformances,
667667
CanGenericSignature genericSig = CanGenericSignature(),
668-
bool shouldSubstituteOpaqueArchetypes = false) const;
668+
SubstOptions options = None) const;
669669

670670
SILType subst(Lowering::TypeConverter &tc,
671671
InFlightSubstitution &IFS,

0 commit comments

Comments
 (0)