Skip to content

Commit 75e21e6

Browse files
committed
AST: Use PackElementType to model references to pack elements of outer expansions
1 parent 8bae307 commit 75e21e6

12 files changed

+252
-90
lines changed

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.

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,8 @@ static Type getTypeForDWARFMangling(Type t) {
659659
return t;
660660
},
661661
MakeAbstractConformanceForGenericType(),
662-
SubstFlags::AllowLoweredTypes);
662+
SubstFlags::AllowLoweredTypes |
663+
SubstFlags::PreservePackExpansionLevel);
663664
}
664665

665666
std::string ASTMangler::mangleTypeForDebugger(Type Ty, GenericSignature sig) {

lib/AST/GenericEnvironment.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,8 @@ Type TypeBase::mapTypeOutOfContext() {
432432
assert(!hasTypeParameter() && "already have an interface type");
433433
return Type(this).subst(MapTypeOutOfContext(),
434434
MakeAbstractConformanceForGenericType(),
435-
SubstFlags::AllowLoweredTypes);
435+
SubstFlags::AllowLoweredTypes |
436+
SubstFlags::PreservePackExpansionLevel);
436437
}
437438

438439
class GenericEnvironment::NestedTypeStorage
@@ -637,7 +638,8 @@ Type GenericEnvironment::mapTypeIntoContext(
637638
type = maybeApplyOuterContextSubstitutions(type);
638639
Type result = type.subst(QueryInterfaceTypeSubstitutions(this),
639640
lookupConformance,
640-
SubstFlags::AllowLoweredTypes);
641+
SubstFlags::AllowLoweredTypes |
642+
SubstFlags::PreservePackExpansionLevel);
641643
assert((!result->hasTypeParameter() || result->hasError() ||
642644
getKind() == Kind::Opaque) &&
643645
"not fully substituted");
@@ -787,16 +789,19 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
787789
// Map element archetypes to the pack archetypes by converting
788790
// element types to interface types and adding the isParameterPack
789791
// bit. Then, map type parameters to archetypes.
790-
return type.subst([&](SubstitutableType *type) {
791-
auto *genericParam = type->getAs<GenericTypeParamType>();
792-
if (!genericParam)
793-
return Type();
794-
795-
if (auto *packParam = packParamForElement[{genericParam}])
796-
return substitutions(packParam);
797-
798-
return substitutions(genericParam);
799-
}, LookUpConformanceInSignature(sig.getPointer()));
792+
return type.subst(
793+
[&](SubstitutableType *type) {
794+
auto *genericParam = type->getAs<GenericTypeParamType>();
795+
if (!genericParam)
796+
return Type();
797+
798+
if (auto *packParam = packParamForElement[{genericParam}])
799+
return substitutions(packParam);
800+
801+
return substitutions(genericParam);
802+
},
803+
LookUpConformanceInSignature(sig.getPointer()),
804+
SubstFlags::PreservePackExpansionLevel);
800805
}
801806

802807
namespace {

lib/AST/ProtocolConformanceRef.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
119119
}
120120

121121
// Check the conformance map.
122-
return IFS.lookupConformance(origType->getCanonicalType(), substType, proto);
122+
// FIXME: Pack element level?
123+
return IFS.lookupConformance(origType->getCanonicalType(), substType, proto,
124+
/*level=*/0);
123125
}
124126

125127
ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext() const {
@@ -130,7 +132,8 @@ ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext() cons
130132
return archetypeType->getInterfaceType();
131133
return type;
132134
},
133-
MakeAbstractConformanceForGenericType());
135+
MakeAbstractConformanceForGenericType(),
136+
SubstFlags::PreservePackExpansionLevel);
134137
return ProtocolConformanceRef(concrete);
135138
} else if (isPack()) {
136139
return getPack()->subst(
@@ -139,7 +142,8 @@ ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext() cons
139142
return archetypeType->getInterfaceType();
140143
return type;
141144
},
142-
MakeAbstractConformanceForGenericType());
145+
MakeAbstractConformanceForGenericType(),
146+
SubstFlags::PreservePackExpansionLevel);
143147
}
144148

145149
return *this;

lib/AST/RequirementEnvironment.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ RequirementEnvironment::RequirementEnvironment(
6969
MakeAbstractConformanceForGenericType();
7070

7171
auto substConcreteType = concreteType.subst(
72-
conformanceToWitnessThunkTypeFn, conformanceToWitnessThunkConformanceFn);
72+
conformanceToWitnessThunkTypeFn,
73+
conformanceToWitnessThunkConformanceFn,
74+
SubstFlags::PreservePackExpansionLevel);
7375

7476
// Calculate the depth at which the requirement's generic parameters
7577
// appear in the witness thunk signature.

lib/AST/SubstitutionMap.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,8 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
247247
CanType depTy = req.getFirstType()->getCanonicalType();
248248
auto replacement = depTy.subst(IFS);
249249
auto *proto = req.getProtocolDecl();
250-
auto conformance = IFS.lookupConformance(depTy, replacement, proto);
250+
auto conformance = IFS.lookupConformance(depTy, replacement, proto,
251+
/*level=*/0);
251252
conformances.push_back(conformance);
252253
}
253254

@@ -440,7 +441,9 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
440441
}
441442

442443
SubstitutionMap SubstitutionMap::mapReplacementTypesOutOfContext() const {
443-
return subst(MapTypeOutOfContext(), MakeAbstractConformanceForGenericType());
444+
return subst(MapTypeOutOfContext(),
445+
MakeAbstractConformanceForGenericType(),
446+
SubstFlags::PreservePackExpansionLevel);
444447
}
445448

446449
SubstitutionMap SubstitutionMap::subst(SubstitutionMap subMap,
@@ -829,5 +832,7 @@ SubstitutionMap SubstitutionMap::mapIntoTypeExpansionContext(
829832
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
830833
context.getContext(), context.getResilienceExpansion(),
831834
context.isWholeModuleContext());
832-
return this->subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
835+
return this->subst(replacer, replacer,
836+
SubstFlags::SubstituteOpaqueArchetypes |
837+
SubstFlags::PreservePackExpansionLevel);
833838
}

0 commit comments

Comments
 (0)