Sema: Add DeclContext::getGenericTypeContextDepth()

Now that generic signatures of types include generic parameters
introduced by outer generic functions, we need to know to skip
them when forming bound generic types or substitutions.

Add a function that computes the depth of the innermost generic
context that is not a generic type context.
This commit is contained in:
Slava Pestov
2015-12-14 02:00:04 -08:00
parent f43a5fec87
commit 74e575e638
7 changed files with 114 additions and 25 deletions

View File

@@ -531,6 +531,7 @@ namespace {
ConstraintSystem &cs;
DeclContext *dc;
bool skipProtocolSelfConstraint;
unsigned minOpeningDepth;
DependentTypeOpener *opener;
ConstraintLocatorBuilder &locator;
llvm::DenseMap<CanType, TypeVariableType *> &replacements;
@@ -541,13 +542,14 @@ namespace {
ConstraintSystem &cs,
DeclContext *dc,
bool skipProtocolSelfConstraint,
unsigned minOpeningDepth,
DependentTypeOpener *opener,
ConstraintLocatorBuilder &locator,
llvm::DenseMap<CanType, TypeVariableType *> &replacements,
GetTypeVariable &getTypeVariable)
: cs(cs), dc(dc), skipProtocolSelfConstraint(skipProtocolSelfConstraint),
opener(opener), locator(locator), replacements(replacements),
getTypeVariable(getTypeVariable) { }
minOpeningDepth(minOpeningDepth), opener(opener), locator(locator),
replacements(replacements), getTypeVariable(getTypeVariable) { }
Type operator()(Type type) {
assert(!type->is<PolymorphicFunctionType>() && "Shouldn't get here");
@@ -616,6 +618,7 @@ namespace {
genericFn->getGenericParams(),
genericFn->getRequirements(),
skipProtocolSelfConstraint,
minOpeningDepth,
opener,
locator,
replacements);
@@ -651,6 +654,7 @@ namespace {
unboundDecl->getGenericParamTypes(),
unboundDecl->getGenericRequirements(),
/*skipProtocolSelfConstraint=*/false,
minOpeningDepth,
opener,
locator,
replacements);
@@ -676,11 +680,13 @@ Type ConstraintSystem::openType(
llvm::DenseMap<CanType, TypeVariableType *> &replacements,
DeclContext *dc,
bool skipProtocolSelfConstraint,
unsigned minOpeningDepth,
DependentTypeOpener *opener) {
GetTypeVariable getTypeVariable{*this, locator, opener};
ReplaceDependentTypes replaceDependentTypes(*this, dc,
skipProtocolSelfConstraint,
minOpeningDepth,
opener,
locator,
replacements, getTypeVariable);
@@ -831,7 +837,10 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
assert(func->isOperator() && "Lookup should only find operators");
auto openedType = openType(func->getInterfaceType(), locator,
replacements, func, false, opener);
replacements, func,
false,
value->getDeclContext()->getGenericTypeContextDepth(),
opener);
auto openedFnType = openedType->castTo<FunctionType>();
// If this is a method whose result type is dynamic Self, replace
@@ -869,7 +878,10 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
// Open the type.
type = openType(type, locator, replacements,
value->getInnermostDeclContext(), false, opener);
value->getInnermostDeclContext(),
false,
value->getDeclContext()->getGenericTypeContextDepth(),
opener);
// If we opened up any type variables, record the replacements.
recordOpenedTypes(locator, replacements);
@@ -906,6 +918,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
replacements,
value->getPotentialGenericDeclContext(),
/*skipProtocolSelfConstraint=*/false,
value->getDeclContext()->getGenericTypeContextDepth(),
opener);
// If we opened up any type variables, record the replacements.
@@ -919,6 +932,7 @@ void ConstraintSystem::openGeneric(
ArrayRef<GenericTypeParamType *> params,
ArrayRef<Requirement> requirements,
bool skipProtocolSelfConstraint,
unsigned minOpeningDepth,
DependentTypeOpener *opener,
ConstraintLocatorBuilder locator,
llvm::DenseMap<CanType, TypeVariableType *> &replacements) {
@@ -927,9 +941,8 @@ void ConstraintSystem::openGeneric(
// Create the type variables for the generic parameters.
for (auto gp : params) {
// If we have a mapping for this type parameter, there's nothing else to do.
if (opener && opener->mapGenericTypeParamType(gp)) {
if (opener && opener->mapGenericTypeParamType(gp))
continue;
}
ArchetypeType *archetype = ArchetypeBuilder::mapTypeIntoContext(dc, gp)
->castTo<ArchetypeType>();
@@ -940,6 +953,9 @@ void ConstraintSystem::openGeneric(
TVO_MustBeMaterializable);
replacements[gp->getCanonicalType()] = typeVar;
if (gp->getDepth() < minOpeningDepth)
addConstraint(ConstraintKind::Bind, typeVar, archetype, locatorPtr);
// Note that we opened a generic parameter to a type variable.
if (opener) {
Type replacementType;
@@ -955,6 +971,7 @@ void ConstraintSystem::openGeneric(
GetTypeVariable getTypeVariable{*this, locator, opener};
ReplaceDependentTypes replaceDependentTypes(*this, dc,
skipProtocolSelfConstraint,
minOpeningDepth,
opener, locator, replacements,
getTypeVariable);
@@ -1128,21 +1145,28 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
auto isClassBoundExistential = false;
llvm::DenseMap<CanType, TypeVariableType *> replacements;
if (auto genericFn = value->getInterfaceType()->getAs<GenericFunctionType>()){
openedType = openType(genericFn, locator, replacements, dc,
/*skipProtocolSelfConstraint=*/true, opener);
openedType = openType(genericFn, locator, replacements,
dc,
/*skipProtocolSelfConstraint=*/true,
value->getDeclContext()->getGenericTypeContextDepth(),
opener);
} else {
openedType = TC.getUnopenedTypeOfReference(value, baseTy, DC, base,
/*wantInterfaceType=*/true);
Type selfTy;
if (auto sig = dc->getGenericSignatureOfContext()) {
unsigned minOpeningDepth =
value->getDeclContext()->getGenericTypeContextDepth();
// Open up the generic parameter list for the container.
openGeneric(dc, sig->getGenericParams(), sig->getRequirements(),
/*skipProtocolSelfConstraint=*/true,
/*skipProtocolSelfConstraint=*/true, minOpeningDepth,
opener, locator, replacements);
// Open up the type of the member.
openedType = openType(openedType, locator, replacements, nullptr, false,
openedType = openType(openedType, locator, replacements, nullptr, false,
value->getDeclContext()->getGenericTypeContextDepth(),
opener);
// Determine the object type of 'self'.