void TypeChecker::validateGenericTypeSignature(GenericTypeDecl *typeDecl) { if (typeDecl->isValidatingGenericSignature()) return; typeDecl->setIsValidatingGenericSignature(); SWIFT_DEFER { typeDecl->setIsValidatingGenericSignature(false); }; auto *gp = typeDecl->getGenericParams(); auto *dc = typeDecl->getDeclContext(); if (!gp) { auto *parentEnv = dc->getGenericEnvironmentOfContext(); typeDecl->setGenericEnvironment(parentEnv); return; } auto *sig = validateGenericSignature(gp, dc, dc->getGenericSignatureOfContext(), /*allowConcreteGenericParams=*/false, nullptr); assert(sig->getInnermostGenericParams().size() == typeDecl->getGenericParams()->size()); revertGenericParamList(gp); ArchetypeBuilder builder = createArchetypeBuilder(typeDecl->getModuleContext()); auto *parentSig = dc->getGenericSignatureOfContext(); auto *parentEnv = dc->getGenericEnvironmentOfContext(); checkGenericParamList(&builder, gp, parentSig, parentEnv, nullptr); auto *env = builder.getGenericEnvironment(sig); typeDecl->setGenericEnvironment(env); finalizeGenericParamList(gp, sig, env, typeDecl); }
void TypeChecker::markInvalidGenericSignature(ValueDecl *VD) { GenericParamList *genericParams; if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD)) genericParams = AFD->getGenericParams(); else genericParams = cast<GenericTypeDecl>(VD)->getGenericParams(); // If there aren't any generic parameters at this level, we're done. if (genericParams == nullptr) return; DeclContext *DC = VD->getDeclContext(); ArchetypeBuilder builder = createArchetypeBuilder(DC->getParentModule()); if (auto sig = DC->getGenericSignatureOfContext()) builder.addGenericSignature(sig, true); // Visit each of the generic parameters. for (auto param : *genericParams) builder.addGenericParameter(param); // Wire up the archetypes. for (auto GP : *genericParams) GP->setArchetype(builder.getArchetype(GP)); genericParams->setAllArchetypes( Context.AllocateCopy(builder.getAllArchetypes())); }
GenericSignature *TypeChecker::validateGenericSignature( GenericParamList *genericParams, DeclContext *dc, GenericSignature *parentSig, bool allowConcreteGenericParams, std::function<void(ArchetypeBuilder &)> inferRequirements) { assert(genericParams && "Missing generic parameters?"); // Create the archetype builder. Module *module = dc->getParentModule(); ArchetypeBuilder builder = createArchetypeBuilder(module); // Type check the generic parameters, treating all generic type // parameters as dependent, unresolved. DependentGenericTypeResolver dependentResolver(builder); checkGenericParamList(&builder, genericParams, parentSig, nullptr, &dependentResolver); /// Perform any necessary requirement inference. if (inferRequirements) inferRequirements(builder); // Finalize the generic requirements. (void)builder.finalize(genericParams->getSourceRange().Start, allowConcreteGenericParams); // The archetype builder now has all of the requirements, although there might // still be errors that have not yet been diagnosed. Revert the signature // and type-check it again, completely. revertGenericParamList(genericParams); CompleteGenericTypeResolver completeResolver(*this, builder); checkGenericParamList(nullptr, genericParams, nullptr, nullptr, &completeResolver); (void)builder.diagnoseRemainingRenames(genericParams->getSourceRange().Start); // Record the generic type parameter types and the requirements. auto sig = builder.getGenericSignature(); // Debugging of the archetype builder and generic signature generation. if (Context.LangOpts.DebugGenericSignatures) { dc->printContext(llvm::errs()); llvm::errs() << "\n"; builder.dump(llvm::errs()); llvm::errs() << "Generic signature: "; sig->print(llvm::errs()); llvm::errs() << "\n"; llvm::errs() << "Canonical generic signature: "; sig->getCanonicalSignature()->print(llvm::errs()); llvm::errs() << "\n"; } return sig; }
/// Add the generic parameters and requirements from the parent context to the /// archetype builder. static void addContextParamsAndRequirements(ArchetypeBuilder &builder, DeclContext *dc, bool adoptArchetypes) { if (!dc->isTypeContext()) return; if (auto sig = dc->getGenericSignatureOfContext()) { // Add generic signature from this context. builder.addGenericSignature(sig, adoptArchetypes); } }
/// Finalize the given generic parameter list, assigning archetypes to /// the generic parameters. void TypeChecker::finalizeGenericParamList(ArchetypeBuilder &builder, GenericParamList *genericParams, DeclContext *dc) { Accessibility access; if (auto *fd = dyn_cast<FuncDecl>(dc)) access = fd->getFormalAccess(); else if (auto *nominal = dyn_cast<NominalTypeDecl>(dc)) access = nominal->getFormalAccess(); else access = Accessibility::Internal; // Wire up the archetypes. for (auto GP : *genericParams) { GP->setArchetype(builder.getArchetype(GP)); checkInheritanceClause(GP); if (!GP->hasAccessibility()) GP->setAccessibility(access); } genericParams->setAllArchetypes( Context.AllocateCopy(builder.getAllArchetypes())); #ifndef NDEBUG // Record archetype contexts. for (auto archetype : genericParams->getAllArchetypes()) { if (Context.ArchetypeContexts.count(archetype) == 0) Context.ArchetypeContexts[archetype] = dc; } #endif // Replace the generic parameters with their archetypes throughout the // types in the requirements. // FIXME: This should not be necessary at this level; it is a transitional // step. for (auto &Req : genericParams->getRequirements()) { if (Req.isInvalid()) continue; switch (Req.getKind()) { case RequirementReprKind::TypeConstraint: { revertDependentTypeLoc(Req.getSubjectLoc()); if (validateType(Req.getSubjectLoc(), dc)) { Req.setInvalid(); continue; } revertDependentTypeLoc(Req.getConstraintLoc()); if (validateType(Req.getConstraintLoc(), dc)) { Req.setInvalid(); continue; } break; } case RequirementReprKind::SameType: revertDependentTypeLoc(Req.getFirstTypeLoc()); if (validateType(Req.getFirstTypeLoc(), dc)) { Req.setInvalid(); continue; } revertDependentTypeLoc(Req.getSecondTypeLoc()); if (validateType(Req.getSecondTypeLoc(), dc)) { Req.setInvalid(); continue; } break; } } }
GenericSignature *TypeChecker::validateGenericSignature( GenericParamList *genericParams, DeclContext *dc, GenericSignature *outerSignature, std::function<bool(ArchetypeBuilder &)> inferRequirements, bool &invalid) { assert(genericParams && "Missing generic parameters?"); // Create the archetype builder. Module *module = dc->getParentModule(); ArchetypeBuilder builder = createArchetypeBuilder(module); auto *parentSig = (outerSignature ? outerSignature : dc->getGenericSignatureOfContext()); // Type check the generic parameters, treating all generic type // parameters as dependent, unresolved. DependentGenericTypeResolver dependentResolver(builder); if (checkGenericParamList(&builder, genericParams, parentSig, false, &dependentResolver)) { invalid = true; } /// Perform any necessary requirement inference. if (inferRequirements && inferRequirements(builder)) { invalid = true; } // Finalize the generic requirements. (void)builder.finalize(genericParams->getSourceRange().Start); // The archetype builder now has all of the requirements, although there might // still be errors that have not yet been diagnosed. Revert the signature // and type-check it again, completely. revertGenericParamList(genericParams); CompleteGenericTypeResolver completeResolver(*this, builder); if (checkGenericParamList(nullptr, genericParams, parentSig, false, &completeResolver)) { invalid = true; } // The generic signature is complete and well-formed. Gather the // generic parameter types at all levels. SmallVector<GenericTypeParamType *, 4> allGenericParams; collectGenericParamTypes(genericParams, parentSig, allGenericParams); // Record the generic type parameter types and the requirements. auto sig = builder.getGenericSignature(allGenericParams); // Debugging of the archetype builder and generic signature generation. if (Context.LangOpts.DebugGenericSignatures) { dc->printContext(llvm::errs()); llvm::errs() << "\n"; builder.dump(llvm::errs()); llvm::errs() << "Generic signature: "; sig->print(llvm::errs()); llvm::errs() << "\n"; llvm::errs() << "Canonical generic signature: "; sig->getCanonicalSignature()->print(llvm::errs()); llvm::errs() << "\n"; llvm::errs() << "Canonical generic signature for mangling: "; sig->getCanonicalManglingSignature(*dc->getParentModule()) ->print(llvm::errs()); llvm::errs() << "\n"; } return sig; }
bool TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) { bool invalid = false; // Create the archetype builder. ArchetypeBuilder builder = createArchetypeBuilder(func->getParentModule()); // Type check the function declaration, treating all generic type // parameters as dependent, unresolved. DependentGenericTypeResolver dependentResolver(builder); if (checkGenericFuncSignature(*this, &builder, func, dependentResolver)) invalid = true; // If this triggered a recursive validation, back out: we're done. // FIXME: This is an awful hack. if (func->hasType()) return !func->isInvalid(); // Finalize the generic requirements. (void)builder.finalize(func->getLoc()); // The archetype builder now has all of the requirements, although there might // still be errors that have not yet been diagnosed. Revert the generic // function signature and type-check it again, completely. revertGenericFuncSignature(func); CompleteGenericTypeResolver completeResolver(*this, builder); if (checkGenericFuncSignature(*this, nullptr, func, completeResolver)) invalid = true; // The generic function signature is complete and well-formed. Determine // the type of the generic function. // Collect the complete set of generic parameter types. SmallVector<GenericTypeParamType *, 4> allGenericParams; collectGenericParamTypes(func->getGenericParams(), func->getDeclContext()->getGenericSignatureOfContext(), allGenericParams); auto sig = builder.getGenericSignature(allGenericParams); // Debugging of the archetype builder and generic signature generation. if (sig && Context.LangOpts.DebugGenericSignatures) { func->dumpRef(llvm::errs()); llvm::errs() << "\n"; builder.dump(llvm::errs()); llvm::errs() << "Generic signature: "; sig->print(llvm::errs()); llvm::errs() << "\n"; llvm::errs() << "Canonical generic signature: "; sig->getCanonicalSignature()->print(llvm::errs()); llvm::errs() << "\n"; llvm::errs() << "Canonical generic signature for mangling: "; sig->getCanonicalManglingSignature(*func->getParentModule()) ->print(llvm::errs()); llvm::errs() << "\n"; } func->setGenericSignature(sig); if (invalid) { func->overwriteType(ErrorType::get(Context)); return true; } configureInterfaceType(func); return false; }
bool TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) { bool invalid = false; // Create the archetype builder. ArchetypeBuilder builder = createArchetypeBuilder(func->getParentModule()); // Type check the function declaration, treating all generic type // parameters as dependent, unresolved. DependentGenericTypeResolver dependentResolver(builder); if (checkGenericFuncSignature(*this, &builder, func, dependentResolver)) invalid = true; // If this triggered a recursive validation, back out: we're done. // FIXME: This is an awful hack. if (func->hasType()) return !func->isInvalid(); // Finalize the generic requirements. (void)builder.finalize(func->getLoc()); // The archetype builder now has all of the requirements, although there might // still be errors that have not yet been diagnosed. Revert the generic // function signature and type-check it again, completely. revertGenericFuncSignature(func); CompleteGenericTypeResolver completeResolver(*this, builder); if (checkGenericFuncSignature(*this, nullptr, func, completeResolver)) invalid = true; // The generic function signature is complete and well-formed. Determine // the type of the generic function. // Collect the complete set of generic parameter types. SmallVector<GenericTypeParamType *, 4> allGenericParams; collectGenericParamTypes(func->getGenericParams(), func->getDeclContext()->getGenericSignatureOfContext(), allGenericParams); auto sig = builder.getGenericSignature(allGenericParams); // Debugging of the archetype builder and generic signature generation. if (sig && Context.LangOpts.DebugGenericSignatures) { func->dumpRef(llvm::errs()); llvm::errs() << "\n"; builder.dump(llvm::errs()); llvm::errs() << "Generic signature: "; sig->print(llvm::errs()); llvm::errs() << "\n"; llvm::errs() << "Canonical generic signature: "; sig->getCanonicalSignature()->print(llvm::errs()); llvm::errs() << "\n"; llvm::errs() << "Canonical generic signature for mangling: "; sig->getCanonicalManglingSignature(*func->getParentModule()) ->print(llvm::errs()); llvm::errs() << "\n"; } func->setGenericSignature(sig); if (invalid) { func->overwriteType(ErrorType::get(Context)); return true; } // Compute the function type. Type funcTy; Type initFuncTy; if (auto fn = dyn_cast<FuncDecl>(func)) { funcTy = fn->getBodyResultTypeLoc().getType(); if (!funcTy) { funcTy = TupleType::getEmpty(Context); } else { funcTy = getResultType(*this, fn, funcTy); } } else if (auto ctor = dyn_cast<ConstructorDecl>(func)) { // FIXME: shouldn't this just be // ctor->getDeclContext()->getDeclaredInterfaceType()? if (ctor->getDeclContext()->getAsProtocolOrProtocolExtensionContext()) { funcTy = ctor->getDeclContext()->getProtocolSelf()->getDeclaredType(); } else { funcTy = ctor->getExtensionType()->getAnyNominal() ->getDeclaredInterfaceType(); } // Adjust result type for failability. if (ctor->getFailability() != OTK_None) funcTy = OptionalType::get(ctor->getFailability(), funcTy); initFuncTy = funcTy; } else { assert(isa<DestructorDecl>(func)); funcTy = TupleType::getEmpty(Context); } auto paramLists = func->getParameterLists(); SmallVector<ParameterList*, 4> storedParamLists; // FIXME: Destructors don't have the '()' pattern in their signature, so // paste it here. if (isa<DestructorDecl>(func)) { assert(paramLists.size() == 1 && "Only the self paramlist"); storedParamLists.push_back(paramLists[0]); storedParamLists.push_back(ParameterList::createEmpty(Context)); paramLists = storedParamLists; } bool hasSelf = func->getDeclContext()->isTypeContext(); for (unsigned i = 0, e = paramLists.size(); i != e; ++i) { Type argTy; Type initArgTy; Type selfTy; if (i == e-1 && hasSelf) { selfTy = func->computeInterfaceSelfType(/*isInitializingCtor=*/false); // Substitute in our own 'self' parameter. argTy = selfTy; if (initFuncTy) { initArgTy = func->computeInterfaceSelfType(/*isInitializingCtor=*/true); } } else { argTy = paramLists[e - i - 1]->getType(Context); // For an implicit declaration, our argument type will be in terms of // archetypes rather than dependent types. Replace the // archetypes with their corresponding dependent types. if (func->isImplicit()) { argTy = ArchetypeBuilder::mapTypeOutOfContext(func, argTy); } if (initFuncTy) initArgTy = argTy; } auto info = applyFunctionTypeAttributes(func, i); // FIXME: We shouldn't even get here if the function isn't locally generic // to begin with, but fixing that requires a lot of reengineering for local // definitions in generic contexts. if (sig && i == e-1) { if (func->getGenericParams()) { // Collect all generic params referenced in parameter types, // return type or requirements. SmallPtrSet<GenericTypeParamDecl *, 4> referencedGenericParams; argTy.visit([&referencedGenericParams](Type t) { if (isa<GenericTypeParamType>(t.getCanonicalTypeOrNull())) { referencedGenericParams.insert( t->castTo<GenericTypeParamType>()->getDecl()); } }); funcTy.visit([&referencedGenericParams](Type t) { if (isa<GenericTypeParamType>(t.getCanonicalTypeOrNull())) { referencedGenericParams.insert( t->castTo<GenericTypeParamType>()->getDecl()); } }); auto requirements = sig->getRequirements(); for (auto req : requirements) { if (req.getKind() == RequirementKind::SameType) { // Same type requirements may allow for generic // inference, even if this generic parameter // is not mentioned in the function signature. // TODO: Make the test more precise. auto left = req.getFirstType(); auto right = req.getSecondType(); // For now consider any references inside requirements // as a possibility to infer the generic type. left.visit([&referencedGenericParams](Type t) { if (isa<GenericTypeParamType>(t.getCanonicalTypeOrNull())) { referencedGenericParams.insert( t->castTo<GenericTypeParamType>()->getDecl()); } }); right.visit([&referencedGenericParams](Type t) { if (isa<GenericTypeParamType>(t.getCanonicalTypeOrNull())) { referencedGenericParams.insert( t->castTo<GenericTypeParamType>()->getDecl()); } }); } } // Find the depth of the function's own generic parameters. unsigned fnGenericParamsDepth = func->getGenericParams()->getDepth(); // Check that every generic parameter type from the signature is // among referencedArchetypes. for (auto *genParam : sig->getGenericParams()) { auto *paramDecl = genParam->getDecl(); if (paramDecl->getDepth() != fnGenericParamsDepth) continue; if (!referencedGenericParams.count(paramDecl)) { // Produce an error that this generic parameter cannot be bound. diagnose(paramDecl->getLoc(), diag::unreferenced_generic_parameter, paramDecl->getNameStr()); func->setInvalid(); } } } funcTy = GenericFunctionType::get(sig, argTy, funcTy, info); if (initFuncTy) initFuncTy = GenericFunctionType::get(sig, initArgTy, initFuncTy, info); } else { funcTy = FunctionType::get(argTy, funcTy, info); if (initFuncTy) initFuncTy = FunctionType::get(initArgTy, initFuncTy, info); } } // Record the interface type. func->setInterfaceType(funcTy); if (initFuncTy) cast<ConstructorDecl>(func)->setInitializerInterfaceType(initFuncTy); return false; }
/// Collect the set of requirements placed on the given generic parameters and /// their associated types. static void collectRequirements(ArchetypeBuilder &builder, ArrayRef<GenericTypeParamType *> params, SmallVectorImpl<Requirement> &requirements) { typedef ArchetypeBuilder::PotentialArchetype PotentialArchetype; // Find the "primary" potential archetypes, from which we'll collect all // of the requirements. llvm::SmallPtrSet<PotentialArchetype *, 16> knownPAs; llvm::SmallVector<GenericTypeParamType *, 8> primary; for (auto param : params) { auto pa = builder.resolveArchetype(param); assert(pa && "Missing potential archetype for generic parameter"); // We only care about the representative. pa = pa->getRepresentative(); if (knownPAs.insert(pa).second) primary.push_back(param); } // Add all of the conformance and superclass requirements placed on the given // generic parameters and their associated types. unsigned primaryIdx = 0, numPrimary = primary.size(); while (primaryIdx < numPrimary) { unsigned depth = primary[primaryIdx]->getDepth(); // For each of the primary potential archetypes, add the requirements. // Stop when we hit a parameter at a different depth. // FIXME: This algorithm falls out from the way the "all archetypes" lists // are structured. Once those lists no longer exist or are no longer // "the truth", we can simplify this algorithm considerably. unsigned lastPrimaryIdx = primaryIdx; for (unsigned idx = primaryIdx; idx < numPrimary && primary[idx]->getDepth() == depth; ++idx, ++lastPrimaryIdx) { auto param = primary[idx]; auto pa = builder.resolveArchetype(param)->getRepresentative(); // Add other requirements. addRequirements(builder.getModule(), param, pa, knownPAs, requirements); } // For each of the primary potential archetypes, add the nested requirements. for (unsigned idx = primaryIdx; idx < lastPrimaryIdx; ++idx) { auto param = primary[idx]; auto pa = builder.resolveArchetype(param)->getRepresentative(); addNestedRequirements(builder.getModule(), param, pa, knownPAs, requirements); } primaryIdx = lastPrimaryIdx; } // Add all of the same-type requirements. for (auto req : builder.getSameTypeRequirements()) { auto firstType = req.first->getDependentType(builder, false); Type secondType; if (auto concrete = req.second.dyn_cast<Type>()) secondType = concrete; else if (auto secondPA = req.second.dyn_cast<PotentialArchetype*>()) secondType = secondPA->getDependentType(builder, false); if (firstType->is<ErrorType>() || secondType->is<ErrorType>() || firstType->isEqual(secondType)) continue; requirements.push_back(Requirement(RequirementKind::SameType, firstType, secondType)); } }
GenericSignature * TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) { bool invalid = false; // Create the archetype builder. ArchetypeBuilder builder = createArchetypeBuilder(func->getParentModule()); // Type check the function declaration, treating all generic type // parameters as dependent, unresolved. DependentGenericTypeResolver dependentResolver(builder); if (checkGenericFuncSignature(*this, &builder, func, dependentResolver)) invalid = true; // If this triggered a recursive validation, back out: we're done. // FIXME: This is an awful hack. if (func->hasInterfaceType()) return nullptr; // Finalize the generic requirements. (void)builder.finalize(func->getLoc()); // The archetype builder now has all of the requirements, although there might // still be errors that have not yet been diagnosed. Revert the generic // function signature and type-check it again, completely. revertGenericFuncSignature(func); CompleteGenericTypeResolver completeResolver(*this, builder); if (checkGenericFuncSignature(*this, nullptr, func, completeResolver)) invalid = true; if (builder.diagnoseRemainingRenames(func->getLoc())) invalid = true; // The generic function signature is complete and well-formed. Determine // the type of the generic function. auto sig = builder.getGenericSignature(); // For a generic requirement in a protocol, make sure that the requirement // set didn't add any requirements to Self or its associated types. if (!invalid && func->getGenericParams() && isa<ProtocolDecl>(func->getDeclContext())) { auto proto = cast<ProtocolDecl>(func->getDeclContext()); for (auto req : sig->getRequirements()) { // If one of the types in the requirement is dependent on a non-Self // type parameter, this requirement is okay. if (!isSelfDerivedOrConcrete(req.getFirstType()) || !isSelfDerivedOrConcrete(req.getSecondType())) continue; // The conformance of 'Self' to the protocol is okay. if (req.getKind() == RequirementKind::Conformance && req.getSecondType()->getAs<ProtocolType>()->getDecl() == proto && req.getFirstType()->is<GenericTypeParamType>()) continue; diagnose(func, Context.LangOpts.EffectiveLanguageVersion[0] >= 4 ? diag::requirement_restricts_self : diag::requirement_restricts_self_swift3, func->getDescriptiveKind(), func->getFullName(), req.getFirstType().getString(), static_cast<unsigned>(req.getKind()), req.getSecondType().getString()); if (Context.LangOpts.EffectiveLanguageVersion[0] >= 4) invalid = true; } } // Debugging of the archetype builder and generic signature generation. if (Context.LangOpts.DebugGenericSignatures) { func->dumpRef(llvm::errs()); llvm::errs() << "\n"; builder.dump(llvm::errs()); llvm::errs() << "Generic signature: "; sig->print(llvm::errs()); llvm::errs() << "\n"; llvm::errs() << "Canonical generic signature: "; sig->getCanonicalSignature()->print(llvm::errs()); llvm::errs() << "\n"; } if (invalid) { func->setInterfaceType(ErrorType::get(Context)); func->setInvalid(); // null doesn't mean error here: callers still expect the signature. return sig; } configureInterfaceType(func, sig); return sig; }