AST: Remove TypeBase::gatherAllSubstitutions()

This commit is contained in:
Slava Pestov
2017-03-07 20:44:09 -08:00
parent 46600b5f1a
commit 2777c9b478
4 changed files with 1 additions and 176 deletions

View File

@@ -555,106 +555,6 @@ void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {
FORWARD(getDisplayDecls, (Results));
}
SubstitutionList
TypeBase::gatherAllSubstitutions(ModuleDecl *module,
LazyResolver *resolver,
DeclContext *gpContext) {
// FIXME: If there is no module, infer one. This is a hack for callers that
// 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)
module = getAnyNominal()->getParentModule();
// Check the context, introducing the default if needed.
if (!gpContext)
gpContext = getAnyNominal();
assert(gpContext->getAsNominalTypeOrNominalTypeExtensionContext()
== getAnyNominal() && "not a valid context");
auto *genericSig = gpContext->getGenericSignatureOfContext();
if (genericSig == nullptr)
return { };
// If we already have a cached copy of the substitutions, return them.
const ASTContext &ctx = getASTContext();
if (auto known = ctx.getSubstitutions(this, gpContext))
return *known;
// Compute the set of substitutions.
TypeSubstitutionMap substitutions;
// The type itself contains substitutions up to the innermost
// non-type context.
Type parent = this;
ArrayRef<GenericTypeParamType *> genericParams =
genericSig->getGenericParams();
unsigned lastGenericIndex = genericParams.size();
while (parent) {
if (auto boundGeneric = parent->getAs<BoundGenericType>()) {
unsigned index = lastGenericIndex - boundGeneric->getGenericArgs().size();
for (Type arg : boundGeneric->getGenericArgs()) {
auto paramTy = genericParams[index++];
substitutions[
paramTy->getCanonicalType()->castTo<GenericTypeParamType>()] = arg;
}
lastGenericIndex -= boundGeneric->getGenericArgs().size();
parent = boundGeneric->getParent();
continue;
}
if (auto protocol = parent->getAs<ProtocolType>()) {
parent = protocol->getParent();
lastGenericIndex--;
continue;
}
if (auto nominal = parent->getAs<NominalType>()) {
parent = nominal->getParent();
continue;
}
llvm_unreachable("Not a nominal or bound generic type");
}
auto *genericEnv = gpContext->getGenericEnvironmentOfContext();
// Add forwarding substitutions from the outer context if we have
// a type nested inside a generic function.
auto *parentDC = gpContext;
while (parentDC->isTypeContext())
parentDC = parentDC->getParent();
if (auto *outerSig = parentDC->getGenericSignatureOfContext()) {
for (auto gp : outerSig->getGenericParams()) {
auto result = substitutions.insert(
{gp->getCanonicalType()->castTo<GenericTypeParamType>(),
genericEnv->mapTypeIntoContext(gp)});
assert(result.second);
(void) result;
}
}
SmallVector<Substitution, 4> result;
genericSig->getSubstitutions(substitutions,
LookUpConformanceInModule(module),
result);
// Before recording substitutions, make sure we didn't end up doing it
// recursively.
if (auto known = ctx.getSubstitutions(this, gpContext))
return *known;
// Copy and record the substitutions.
auto permanentSubs = ctx.AllocateCopy(result,
hasTypeVariable()
? AllocationArena::ConstraintSolver
: AllocationArena::Permanent);
ctx.setSubstitutions(this, gpContext, permanentSubs);
return permanentSubs;
}
Optional<ProtocolConformanceRef>
ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol,
LazyResolver *resolver) {