Skip to content

Commit db4b16e

Browse files
rjmccallhborla
authored andcommitted
[WIP] Always use PackTypes as the substitutions for type parameter packs
This simplifies the representation and allows clients to handle fewer cases. It also removes an ambiguity in the representation which could lead us to have two canonical types for the same type. This is definitely not working yet, but I'm not making progress on it quickly enough to unblock what we need to unblock; it'll have to be fixed in parallel.
1 parent 721b846 commit db4b16e

File tree

9 files changed

+106
-15
lines changed

9 files changed

+106
-15
lines changed

lib/AST/Decl.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4670,8 +4670,12 @@ static Type computeNominalType(NominalTypeDecl *decl, DeclTypeKind kind) {
46704670
// the generic parameter list directly instead of looking
46714671
// at the signature.
46724672
SmallVector<Type, 4> args;
4673-
for (auto param : decl->getGenericParams()->getParams())
4674-
args.push_back(param->getDeclaredInterfaceType());
4673+
for (auto param : decl->getGenericParams()->getParams()) {
4674+
auto argTy = param->getDeclaredInterfaceType();
4675+
if (param->isParameterPack())
4676+
argTy = PackType::getSingletonPackExpansion(argTy);
4677+
args.push_back(argTy);
4678+
}
46754679

46764680
return BoundGenericType::get(decl, ParentTy, args);
46774681
}

lib/AST/GenericEnvironment.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,37 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
681681
}, LookUpConformanceInSignature(sig.getPointer()));
682682
}
683683

684+
namespace {
685+
/// A function suitable for use as a \c TypeSubstitutionFn that produces
686+
/// correct forwarding substitutions for a generic environment.
687+
///
688+
/// This differs from QueryInterfaceTypeSubstitutions only in that it
689+
/// always produces PackTypes for pack parameters.
690+
class BuildForwardingSubstitutions {
691+
QueryInterfaceTypeSubstitutions Query;
692+
693+
public:
694+
BuildForwardingSubstitutions(const GenericEnvironment *self)
695+
: Query(self) { }
696+
697+
Type operator()(SubstitutableType *type) const;
698+
};
699+
} // end anonymous namespace
700+
701+
Type BuildForwardingSubstitutions::operator()(SubstitutableType *type) const {
702+
if (auto resultType = Query(type)) {
703+
auto param = type->castTo<GenericTypeParamType>();
704+
if (!param->isParameterPack())
705+
return resultType;
706+
return PackType::getSingletonPackExpansion(resultType);
707+
}
708+
return Type();
709+
}
710+
684711
SubstitutionMap GenericEnvironment::getForwardingSubstitutionMap() const {
685712
auto genericSig = getGenericSignature();
686713
return SubstitutionMap::get(genericSig,
687-
QueryInterfaceTypeSubstitutions(this),
714+
BuildForwardingSubstitutions(this),
688715
MakeAbstractConformanceForGenericType());
689716
}
690717

lib/AST/GenericSignature.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -579,10 +579,13 @@ unsigned GenericParamKey::findIndexIn(
579579

580580
SubstitutionMap GenericSignatureImpl::getIdentitySubstitutionMap() const {
581581
return SubstitutionMap::get(const_cast<GenericSignatureImpl *>(this),
582-
[](SubstitutableType *t) -> Type {
583-
return Type(cast<GenericTypeParamType>(t));
584-
},
585-
MakeAbstractConformanceForGenericType());
582+
[](SubstitutableType *t) -> Type {
583+
auto param = cast<GenericTypeParamType>(t);
584+
if (!param->isParameterPack())
585+
return param;
586+
return PackType::getSingletonPackExpansion(param);
587+
},
588+
MakeAbstractConformanceForGenericType());
586589
}
587590

588591
GenericTypeParamType *GenericSignatureImpl::getSugaredType(

lib/AST/SubstitutionMap.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
226226

227227
// Record the replacement.
228228
Type replacement = Type(gp).subst(subs, lookupConformance);
229+
230+
assert((!replacement || replacement->hasError() ||
231+
gp->isParameterPack() == replacement->is<PackType>()) &&
232+
"replacement for pack parameter must be a pack type");
233+
229234
replacementTypes.push_back(replacement);
230235
});
231236

lib/AST/Type.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4502,6 +4502,24 @@ operator()(CanType dependentType, Type conformingReplacementType,
45024502
ProtocolConformanceRef MakeAbstractConformanceForGenericType::
45034503
operator()(CanType dependentType, Type conformingReplacementType,
45044504
ProtocolDecl *conformedProtocol) const {
4505+
// The places that use this can also produce conformance packs, generally
4506+
// just for singleton pack expansions.
4507+
if (auto conformingPack = conformingReplacementType->getAs<PackType>()) {
4508+
SmallVector<ProtocolConformanceRef, 4> conformances;
4509+
for (auto conformingPackElt : conformingPack->getElementTypes()) {
4510+
// Look through pack expansions; there's no equivalent conformance
4511+
// expansion right now.
4512+
auto expansion = conformingPackElt->getAs<PackExpansionType>();
4513+
if (expansion) conformingPackElt = expansion->getPatternType();
4514+
4515+
auto conformance =
4516+
(*this)(dependentType, conformingPackElt, conformedProtocol);
4517+
conformances.push_back(conformance);
4518+
}
4519+
return ProtocolConformanceRef(
4520+
PackConformance::get(conformingPack, conformedProtocol, conformances));
4521+
}
4522+
45054523
assert((conformingReplacementType->is<ErrorType>() ||
45064524
conformingReplacementType->is<SubstitutableType>() ||
45074525
conformingReplacementType->is<DependentMemberType>() ||
@@ -4967,6 +4985,9 @@ TypeBase::getContextSubstitutions(const DeclContext *dc,
49674985
else if (genericEnv)
49684986
substTy = genericEnv->mapTypeIntoContext(gp);
49694987

4988+
if (gp->isParameterPack() && !substTy->hasError())
4989+
substTy = PackType::getSingletonPackExpansion(substTy);
4990+
49704991
auto result = substitutions.insert(
49714992
{gp->getCanonicalType()->castTo<GenericTypeParamType>(),
49724993
substTy});

lib/IRGen/GenPack.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,18 @@ static llvm::Value *bindWitnessTableAtIndex(IRGenFunction &IGF,
263263
return wtable;
264264
}
265265

266+
/// Find the pack archetype for the given interface type in the given
267+
/// opened element context, which is known to be a forwarding context.
268+
static CanPackArchetypeType
269+
getMappedPackArchetypeType(const OpenedElementContext &context, CanType ty) {
270+
auto packType = cast<PackType>(
271+
context.environment->maybeApplyOuterContextSubstitutions(ty)
272+
->getCanonicalType());
273+
auto archetype = getForwardedPackArchetypeType(packType);
274+
assert(archetype);
275+
return archetype;
276+
}
277+
266278
static void bindElementSignatureRequirementsAtIndex(
267279
IRGenFunction &IGF, OpenedElementContext const &context, llvm::Value *index,
268280
DynamicMetadataRequest request) {
@@ -275,9 +287,7 @@ static void bindElementSignatureRequirementsAtIndex(
275287
break;
276288
case GenericRequirement::Kind::MetadataPack: {
277289
auto ty = requirement.getTypeParameter();
278-
auto patternPackArchetype = cast<PackArchetypeType>(
279-
context.environment->maybeApplyOuterContextSubstitutions(ty)
280-
->getCanonicalType());
290+
auto patternPackArchetype = getMappedPackArchetypeType(context, ty);
281291
auto response =
282292
IGF.emitTypeMetadataRef(patternPackArchetype, request);
283293
auto elementArchetype =
@@ -295,9 +305,7 @@ static void bindElementSignatureRequirementsAtIndex(
295305
case GenericRequirement::Kind::WitnessTablePack: {
296306
auto ty = requirement.getTypeParameter();
297307
auto proto = requirement.getProtocol();
298-
auto patternPackArchetype = cast<PackArchetypeType>(
299-
context.environment->maybeApplyOuterContextSubstitutions(ty)
300-
->getCanonicalType());
308+
auto patternPackArchetype = getMappedPackArchetypeType(context, ty);
301309
auto elementArchetype =
302310
context.environment
303311
->mapPackTypeIntoElementContext(

lib/Sema/CSApply.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,12 @@ Solution::computeSubstitutions(GenericSignature sig,
9595
return SubstitutionMap();
9696

9797
TypeSubstitutionMap subs;
98-
for (const auto &opened : openedTypes->second)
99-
subs[opened.first] = getFixedType(opened.second);
98+
for (const auto &opened : openedTypes->second) {
99+
auto type = getFixedType(opened.second);
100+
if (opened.first->isParameterPack() && !type->is<PackType>())
101+
type = PackType::getSingletonPackExpansion(type);
102+
subs[opened.first] = type;
103+
}
100104

101105
auto lookupConformanceFn =
102106
[&](CanType original, Type replacement,

lib/Sema/CSBindings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,7 @@ void PotentialBindings::infer(Constraint *constraint) {
15011501
break;
15021502

15031503
auto elementType = elementEnv->mapPackTypeIntoElementContext(packType);
1504+
assert(!elementType->is<PackType>());
15041505
addPotentialBinding({elementType, AllowedBindingKind::Exact, constraint});
15051506

15061507
break;

lib/Sema/CSSimplify.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8783,6 +8783,19 @@ ConstraintSystem::simplifyBindTupleOfFunctionParamsConstraint(
87838783
return SolutionKind::Solved;
87848784
}
87858785

8786+
static Type lookThroughSingletonPackExpansion(Type ty) {
8787+
if (auto pack = ty->getAs<PackType>()) {
8788+
if (pack->getNumElements() == 1) {
8789+
if (auto expansion = pack->getElementType(0)->getAs<PackExpansionType>()) {
8790+
auto countType = expansion->getCountType();
8791+
if (countType->isEqual(expansion->getPatternType()))
8792+
return countType;
8793+
}
8794+
}
8795+
}
8796+
return ty;
8797+
}
8798+
87868799
ConstraintSystem::SolutionKind
87878800
ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
87888801
TypeMatchOptions flags,
@@ -8802,6 +8815,11 @@ ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
88028815
return SolutionKind::Solved;
88038816
}
88048817

8818+
// FIXME: I'm not sure this is actually necessary; I may only be seeing
8819+
// this because of something I've screwed up in element generic
8820+
// environments.
8821+
elementType = lookThroughSingletonPackExpansion(elementType);
8822+
88058823
// This constraint only exists to vend bindings.
88068824
auto *packEnv = DC->getGenericEnvironmentOfContext();
88078825

0 commit comments

Comments
 (0)