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; }
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; }
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; }