AST: Refactor Type::gatherAllSubstitutions() to use GenericSignature::getSubstitutions(), NFC

This removes a pile of getAll{Nested,}Archetypes() usages and
greatly simplifies the logic here.
This commit is contained in:
Slava Pestov
2016-08-19 23:45:59 -07:00
parent b671b9f5d5
commit 410062ba66

View File

@@ -558,9 +558,8 @@ TypeBase::gatherAllSubstitutions(Module *module,
// don't have access to the module. It will have to go away once we're
// properly differentiating bound generic types based on the protocol
// conformances visible from a given module.
if (!module) {
if (!module)
module = getAnyNominal()->getParentModule();
}
// Check the context, introducing the default if needed.
if (!gpContext)
@@ -569,8 +568,8 @@ TypeBase::gatherAllSubstitutions(Module *module,
assert(gpContext->getAsNominalTypeOrNominalTypeExtensionContext()
== getAnyNominal() && "not a valid context");
auto *genericParams = gpContext->getGenericParamsOfContext();
if (!genericParams)
auto *genericSig = gpContext->getGenericSignatureOfContext();
if (genericSig == nullptr)
return { };
// If we already have a cached copy of the substitutions, return them.
@@ -596,8 +595,8 @@ TypeBase::gatherAllSubstitutions(Module *module,
for (Type arg : boundGeneric->getGenericArgs()) {
auto gp = genericParams->getParams()[index++];
auto archetype = gp->getArchetype();
substitutions[archetype] = arg;
substitutions[gp->getDeclaredType()->getCanonicalType()
.getPointer()] = arg;
}
parent = CanType(boundGeneric->getParent());
@@ -616,61 +615,33 @@ TypeBase::gatherAllSubstitutions(Module *module,
// Add forwarding substitutions from the outer context if we have
// a type nested inside a generic function.
if (auto *outerGenericParams = parentDC->getGenericParamsOfContext()) {
for (auto archetype : outerGenericParams->getAllNestedArchetypes())
substitutions[archetype] = archetype;
}
if (auto *outerParams = parentDC->getGenericParamsOfContext())
outerParams->getForwardingSubstitutionMap(substitutions);
// Collect all of the archetypes.
SmallVector<ArchetypeType *, 2> allArchetypesList;
ArrayRef<ArchetypeType *> allArchetypes = genericParams->getAllArchetypes();
if (genericParams->getOuterParameters()) {
SmallVector<const GenericParamList *, 2> allGenericParams;
unsigned numArchetypes = 0;
for (; genericParams; genericParams = genericParams->getOuterParameters()) {
allGenericParams.push_back(genericParams);
numArchetypes += genericParams->getAllArchetypes().size();
}
allArchetypesList.reserve(numArchetypes);
for (auto gp = allGenericParams.rbegin(), gpEnd = allGenericParams.rend();
gp != gpEnd; ++gp) {
allArchetypesList.append((*gp)->getAllArchetypes().begin(),
(*gp)->getAllArchetypes().end());
}
allArchetypes = allArchetypesList;
}
auto lookupConformanceFn =
[&](Type replacement, ProtocolType *protoType)
-> ProtocolConformanceRef {
// For each of the archetypes, compute the substitution.
bool hasTypeVariables = canon->hasTypeVariable();
SmallVector<Substitution, 4> resultSubstitutions;
resultSubstitutions.resize(allArchetypes.size());
unsigned index = 0;
for (auto archetype : allArchetypes) {
// Substitute into the type.
auto type = Type(archetype).subst(module, substitutions, SubstOptions());
if (!type)
type = ErrorType::get(module->getASTContext());
auto *proto = protoType->getDecl();
SmallVector<ProtocolConformanceRef, 4> conformances;
for (auto proto : archetype->getConformsTo()) {
// If the type is a type variable or is dependent, just fill in empty
// conformances.
if (type->is<TypeVariableType>() || type->isTypeParameter()) {
conformances.push_back(ProtocolConformanceRef(proto));
// If the type is a type variable or is dependent, just fill in empty
// conformances.
if (replacement->is<TypeVariableType>() || replacement->isTypeParameter())
return ProtocolConformanceRef(proto);
// Otherwise, find the conformances.
} else {
if (auto conforms = module->lookupConformance(type, proto, resolver))
conformances.push_back(*conforms);
else
conformances.push_back(ProtocolConformanceRef(proto));
}
}
// Otherwise, find the conformance.
auto conforms = module->lookupConformance(replacement, proto, resolver);
if (conforms)
return *conforms;
// Record this substitution.
resultSubstitutions[index] = {type, ctx.AllocateCopy(conformances)};
++index;
}
// FIXME: Should we ever end up here?
return ProtocolConformanceRef(proto);
};
SmallVector<Substitution, 4> result;
genericSig->getSubstitutions(*module, substitutions,
lookupConformanceFn,
result);
// Before recording substitutions, make sure we didn't end up doing it
// recursively.
@@ -678,7 +649,8 @@ TypeBase::gatherAllSubstitutions(Module *module,
return *known;
// Copy and record the substitutions.
auto permanentSubs = ctx.AllocateCopy(resultSubstitutions,
bool hasTypeVariables = canon->hasTypeVariable();
auto permanentSubs = ctx.AllocateCopy(result,
hasTypeVariables
? AllocationArena::ConstraintSolver
: AllocationArena::Permanent);