diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 46120895b06..af7339db712 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -2448,6 +2448,12 @@ public: NumGenericParams }; } + /// Retrieve the innermost generic parameters. + /// + /// Given a generic signature for a nested generic type, produce an + /// array of the generic parameters for the innermost generic type. + ArrayRef getInnermostGenericParams() const; + /// Retrieve the requirements. ArrayRef getRequirements() const { const void *genericParams = getGenericParams().end(); diff --git a/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp index a5292e7b517..f1b49cf1f7f 100644 --- a/lib/AST/ArchetypeBuilder.cpp +++ b/lib/AST/ArchetypeBuilder.cpp @@ -1020,7 +1020,7 @@ public: return Action::Continue; auto genericSig = boundGeneric->getDecl()->getGenericSignature(); - auto params = genericSig->getGenericParams(); + auto params = genericSig->getInnermostGenericParams(); auto args = boundGeneric->getGenericArgs(); // Produce substitutions from the generic parameters to the actual diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 4fcd3a01aec..beb4718c630 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1395,7 +1395,11 @@ DeclContext *ValueDecl::getPotentialGenericDeclContext() { if (auto NTD = dyn_cast(this)) return NTD; - return getDeclContext(); + auto parentDC = getDeclContext(); + if (parentDC->isTypeContext()) + return parentDC; + + return nullptr; } Type ValueDecl::getInterfaceType() const { @@ -1519,6 +1523,22 @@ GenericSignature::GenericSignature(ArrayRef params, CanonicalSignatureOrASTContext = (ASTContext *)nullptr; } +ArrayRef +GenericSignature::getInnermostGenericParams() const { + auto params = getGenericParams(); + + // Find the point at which the depth changes. + unsigned depth = params.back()->getDepth(); + for (unsigned n = params.size(); n > 0; --n) { + if (params[n-1]->getDepth() != depth) { + return params.slice(n); + } + } + + // All parameters are at the same depth. + return params; +} + void NominalTypeDecl::setGenericSignature(GenericSignature *sig) { assert(!GenericSig && "Already have generic signature"); GenericSig = sig; diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index 3b5a8c60ea0..bdc6bb64665 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -138,7 +138,12 @@ GenericParamList *DeclContext::getGenericParamsOfContext() const { if (auto GP = AFD->getGenericParams()) return GP; - return AFD->getDeclContext()->getGenericParamsOfContext(); + // If we're within a type context, pick up the generic signature + // of that context. + if (AFD->getDeclContext()->isTypeContext()) + return AFD->getDeclContext()->getGenericParamsOfContext(); + + return nullptr; } case DeclContextKind::NominalTypeDecl: { @@ -146,7 +151,10 @@ GenericParamList *DeclContext::getGenericParamsOfContext() const { if (auto gp = nominal->getGenericParams()) return gp; - return nominal->getDeclContext()->getGenericParamsOfContext(); + if (nominal->getDeclContext()->isTypeContext()) + return nominal->getDeclContext()->getGenericParamsOfContext(); + + return nullptr; } case DeclContextKind::ExtensionDecl: @@ -168,14 +176,26 @@ GenericSignature *DeclContext::getGenericSignatureOfContext() const { auto *AFD = cast(this); if (auto GFT = AFD->getInterfaceType()->getAs()) return GFT->getGenericSignature(); - return AFD->getDeclContext()->getGenericSignatureOfContext(); + + // If we're within a type context, pick up the generic signature + // of that context. + if (AFD->getDeclContext()->isTypeContext()) + return AFD->getDeclContext()->getGenericSignatureOfContext(); + + return nullptr; } case DeclContextKind::NominalTypeDecl: { auto nominal = cast(this); if (auto genericSig = nominal->getGenericSignature()) return genericSig; - return nominal->getDeclContext()->getGenericSignatureOfContext(); + + // If we're within a type context, pick up the generic signature + // of that context. + if (nominal->getDeclContext()->isTypeContext()) + return nominal->getDeclContext()->getGenericSignatureOfContext(); + + return nullptr; } case DeclContextKind::ExtensionDecl: diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp index 85f786912e3..3137b48775c 100644 --- a/lib/SIL/TypeLowering.cpp +++ b/lib/SIL/TypeLowering.cpp @@ -1525,8 +1525,13 @@ mapArchetypeToInterfaceType(const PrimaryArchetypeMap &primaryArchetypes, CanType TypeConverter::getInterfaceTypeOutOfContext(CanType contextTy, DeclContext *context) const { - return getInterfaceTypeOutOfContext(contextTy, - context->getGenericParamsOfContext()); + GenericParamList *genericParams; + do { + genericParams = context->getGenericParamsOfContext(); + context = context->getParent(); + } while (!genericParams && context); + + return getInterfaceTypeOutOfContext(contextTy, genericParams); } CanType diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index e61b8216f01..71338ab49d3 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -933,27 +933,6 @@ static void addSelfConstraint(ConstraintSystem &cs, Type objectTy, Type selfTy, cs.getConstraintLocator(locator)); } -/// Collect all of the generic parameters and requirements from the -/// given context and its outer contexts. -static void collectContextParamsAndRequirements( - DeclContext *dc, - SmallVectorImpl &genericParams, - SmallVectorImpl &genericRequirements) { - if (!dc->isTypeContext()) - return; - - // Recurse to outer context. - collectContextParamsAndRequirements(dc->getParent(), genericParams, - genericRequirements); - - // Add our generic parameters and requirements. - auto nominal = dc->getDeclaredTypeOfContext()->getAnyNominal(); - genericParams.append(nominal->getGenericParamTypes().begin(), - nominal->getGenericParamTypes().end()); - genericRequirements.append(nominal->getGenericRequirements().begin(), - nominal->getGenericRequirements().end()); -} - /// Rebuilds the given 'self' type using the given object type as the /// replacement for the object type of self. static Type rebuildSelfTypeWithObjectType(Type selfTy, Type objectTy) { @@ -1027,11 +1006,7 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value, } // Figure out the declaration context to use when opening this type. - DeclContext *dc; - if (auto func = dyn_cast(value)) - dc = func; - else - dc = value->getDeclContext(); + DeclContext *dc = value->getPotentialGenericDeclContext(); // Open the type of the generic function or member of a generic type. Type openedType; @@ -1043,15 +1018,10 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value, /*wantInterfaceType=*/true); Type selfTy; - if (dc->isGenericContext()) { + if (auto sig = dc->getGenericSignatureOfContext()) { // Open up the generic parameter list for the container. - auto nominal = dc->getDeclaredTypeOfContext()->getAnyNominal(); llvm::DenseMap replacements; - SmallVector genericParams; - SmallVector genericRequirements; - collectContextParamsAndRequirements(dc, genericParams, - genericRequirements); - openGeneric(dc, genericParams, genericRequirements, + openGeneric(dc, sig->getGenericParams(), sig->getRequirements(), /*skipProtocolSelfConstraint=*/true, opener, locator, replacements); @@ -1060,6 +1030,8 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value, opener); // Determine the object type of 'self'. + auto nominal = value->getDeclContext()->getDeclaredTypeOfContext() + ->getAnyNominal(); if (auto protocol = dyn_cast(nominal)) { // Retrieve the type variable for 'Self'. selfTy = replacements[protocol->getSelf()->getDeclaredType() diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index c0d86a321f0..778dcff13c0 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -203,13 +203,12 @@ static void addContextParamsAndRequirements(ArchetypeBuilder &builder, auto nominal = type->getAnyNominal(); assert(nominal && "Parent context is not a nominal type?"); - // Recurse to outer contexts. - if (auto parentDC = dc->getParent()) - addContextParamsAndRequirements(builder, parentDC); - - // Add generic signature from this context. if (auto sig = nominal->getGenericSignature()) { + // Add generic signature from this context. builder.addGenericSignature(sig); + } else if (auto parentDC = dc->getParent()) { + // Recurse into parent context. + addContextParamsAndRequirements(builder, parentDC); } } @@ -331,36 +330,22 @@ static bool checkGenericParameters(TypeChecker &tc, ArchetypeBuilder *builder, return invalid; } -/// Add the generic parameters and requirements from the parent context to the -/// archetype builder. -static void collectParentGenericParamTypes( - DeclContext *dc, - SmallVectorImpl &allParams) { - auto type = dc->getDeclaredTypeOfContext(); - if (!type || type->is()) - return; - - auto nominal = type->getAnyNominal(); - assert(nominal && "Parent context is not a nominal type?"); - - // Recurse to outer contexts. - if (auto parentDC = dc->getParent()) - collectParentGenericParamTypes(parentDC, allParams); - - allParams.append(nominal->getGenericParamTypes().begin(), - nominal->getGenericParamTypes().end()); -} - /// Collect all of the generic parameter types at every level in the generic /// parameter list. static void collectGenericParamTypes( GenericParamList *genericParams, DeclContext *parentDC, SmallVectorImpl &allParams) { - if (parentDC) - collectParentGenericParamTypes(parentDC, allParams); - - if (genericParams ) { + // If the parent context is a generic type (or nested type thereof), + // add its generic parameters. + if (parentDC->isTypeContext()) { + if (auto parentSig = parentDC->getGenericSignatureOfContext()) { + allParams.append(parentSig->getGenericParams().begin(), + parentSig->getGenericParams().end()); + } + } + + if (genericParams) { // Add our parameters. for (auto param : *genericParams) { allParams.push_back(param->getDeclaredType() @@ -837,15 +822,10 @@ GenericSignature *TypeChecker::validateGenericSignature( invalid = true; } - /// Perform any necessary requirement inference. - if (inferRequirements && inferRequirements(builder)) { - invalid = true; - } - - // The generic function signature is complete and well-formed. Gather - // the generic parameter types at this level. + // The generic signature is complete and well-formed. Gather the + // generic parameter types at all levels. SmallVector allGenericParams; - collectGenericParamTypes(genericParams, nullptr, allGenericParams); + collectGenericParamTypes(genericParams, dc, allGenericParams); // Collect the requirements placed on the generic parameter types. // FIXME: This ends up copying all of the requirements from outer scopes,