Handle nested generic extensions in TypeBase::gatherAllSubstitutions().

The code in TypeBase::gatherAllSubstitutions() walks a declaration
context and type to form a complete set of substitutions for a
(nested) type. When provided with a context for a nested
extension---e.g., "extension OuterGeneric.InnerGeneric", it would skip
over OuterGeneric due to the lexical nesting of DeclContexts not
matching the semantic nesting.

Teach this function to determine the type parameters without walking DeclContexts.
This commit is contained in:
Doug Gregor
2016-11-06 01:48:26 -08:00
parent ba06709eca
commit 4cadee421b

View File

@@ -586,28 +586,24 @@ TypeBase::gatherAllSubstitutions(Module *module,
// The type itself contains substitutions up to the innermost
// non-type context.
CanType parent(canon);
auto *parentDC = gpContext;
ArrayRef<GenericTypeParamType *> genericParams =
genericSig->getGenericParams();
unsigned lastGenericIndex = genericParams.size();
while (parent) {
if (auto boundGeneric = dyn_cast<BoundGenericType>(parent)) {
auto genericSig = parentDC->getGenericSignatureOfContext();
unsigned index = 0;
assert(boundGeneric->getGenericArgs().size() ==
genericSig->getInnermostGenericParams().size());
unsigned index = lastGenericIndex - boundGeneric->getGenericArgs().size();
for (Type arg : boundGeneric->getGenericArgs()) {
auto paramTy = genericSig->getInnermostGenericParams()[index++];
auto paramTy = genericParams[index++];
substitutions[paramTy->getCanonicalType().getPointer()] = arg;
}
lastGenericIndex -= boundGeneric->getGenericArgs().size();
parent = CanType(boundGeneric->getParent());
parentDC = parentDC->getParent();
continue;
}
if (auto nominal = dyn_cast<NominalType>(parent)) {
parent = CanType(nominal->getParent());
parentDC = parentDC->getParent();
continue;
}
@@ -616,6 +612,9 @@ TypeBase::gatherAllSubstitutions(Module *module,
// 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 *outerEnv = parentDC->getGenericEnvironmentOfContext())
for (auto pair : outerEnv->getInterfaceToArchetypeMap()) {
auto result = substitutions.insert(pair);