[SubstitutionMap] Handle substitution of non-canonical generic parameters.

SubstitutionMap::lookupSubstitution() assumed that any type parameter it was
given would already be canonical, and fail (return a null Type) when given
a type parameter that was equivalent to another type parameter but is
not itself canonical. Canonicalize, recursive, and record the replacement
type appropriately.
This commit is contained in:
Doug Gregor
2018-05-07 16:15:06 -07:00
parent 4b5abbddbc
commit dc7a251d4c

View File

@@ -283,8 +283,19 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const {
return replacementType;
}
// Not known.
return Type();
// The generic parameter may not be canonical. Retrieve the canonical
// type, which will be dependent.
CanType canonicalType = genericSig->getCanonicalTypeInContext(genericParam);
// If nothing changed, we don't have a replacement.
if (canonicalType == type) return Type();
// If we're left with a substitutable type, substitute into that.
// First, set the replacement type to an error, to block infinite recursion.
replacementType = ErrorType::get(type);
replacementType = lookupSubstitution(cast<SubstitutableType>(canonicalType));
return replacementType;
}
Optional<ProtocolConformanceRef>