mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user