mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
AST: Add optional GenericEnvironment parameter to TypeBase::getContextSubstitutionMap()
If a generic type appears in a generic function, the old gatherAllSubstitutions() method would map outer generic parameters to archetypes. However, getContextSubstitutionMap() did not map them to anything. I'm trying to unify these methods, so add an optional GenericEnvironment to getContextSubstitutionMap() to support the cases where they're needed. Of course types in generic functions are not supported right now, but not preserving this subtle behavioral difference makes some crashers regress.
This commit is contained in:
@@ -869,11 +869,17 @@ public:
|
||||
/// the context of the extension above will produce substitutions T
|
||||
/// -> Int and U -> String suitable for mapping the type of
|
||||
/// \c SomeArray.
|
||||
///
|
||||
/// \param genericEnv If non-null and the type is nested inside of a
|
||||
/// generic function, generic parameters of the outer context are
|
||||
/// mapped to context archetypes of this generic environment.
|
||||
SubstitutionMap getContextSubstitutionMap(ModuleDecl *module,
|
||||
const DeclContext *dc);
|
||||
const DeclContext *dc,
|
||||
GenericEnvironment *genericEnv=nullptr);
|
||||
|
||||
/// Deprecated version of the above.
|
||||
TypeSubstitutionMap getContextSubstitutions(const DeclContext *dc);
|
||||
TypeSubstitutionMap getContextSubstitutions(const DeclContext *dc,
|
||||
GenericEnvironment *genericEnv=nullptr);
|
||||
|
||||
/// Get the substitutions to apply to the type of the given member as seen
|
||||
/// from this base type.
|
||||
|
||||
@@ -3022,7 +3022,9 @@ Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass,
|
||||
llvm_unreachable("no inheritance relationship between given classes");
|
||||
}
|
||||
|
||||
TypeSubstitutionMap TypeBase::getContextSubstitutions(const DeclContext *dc) {
|
||||
TypeSubstitutionMap
|
||||
TypeBase::getContextSubstitutions(const DeclContext *dc,
|
||||
GenericEnvironment *genericEnv) {
|
||||
assert(dc->isTypeContext());
|
||||
Type baseTy(this);
|
||||
|
||||
@@ -3101,16 +3103,32 @@ TypeSubstitutionMap TypeBase::getContextSubstitutions(const DeclContext *dc) {
|
||||
llvm_unreachable("Bad base type");
|
||||
}
|
||||
|
||||
if (genericEnv) {
|
||||
auto *parentDC = dc;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return substitutions;
|
||||
}
|
||||
|
||||
SubstitutionMap TypeBase::getContextSubstitutionMap(
|
||||
ModuleDecl *module, const DeclContext *dc) {
|
||||
ModuleDecl *module, const DeclContext *dc,
|
||||
GenericEnvironment *genericEnv) {
|
||||
auto *genericSig = dc->getGenericSignatureOfContext();
|
||||
if (genericSig == nullptr)
|
||||
return SubstitutionMap();
|
||||
return genericSig->getSubstitutionMap(
|
||||
QueryTypeSubstitutionMap{getContextSubstitutions(dc)},
|
||||
QueryTypeSubstitutionMap{getContextSubstitutions(dc, genericEnv)},
|
||||
LookUpConformanceInModule(module));
|
||||
}
|
||||
|
||||
@@ -3123,7 +3141,7 @@ TypeSubstitutionMap TypeBase::getMemberSubstitutions(
|
||||
|
||||
// Compute the set of member substitutions to apply.
|
||||
if (memberDC->isTypeContext())
|
||||
substitutions = getContextSubstitutions(memberDC);
|
||||
substitutions = getContextSubstitutions(memberDC, genericEnv);
|
||||
|
||||
// If the member itself is generic, preserve its generic parameters.
|
||||
// We need this since code completion and diagnostics want to be able
|
||||
|
||||
Reference in New Issue
Block a user