void TypeChecker::configureInterfaceType(AbstractFunctionDecl *func, GenericSignature *sig) { Type funcTy; Type initFuncTy = Type(); if (auto fn = dyn_cast<FuncDecl>(func)) { funcTy = fn->getBodyResultTypeLoc().getType(); if (!funcTy) funcTy = TupleType::getEmpty(Context); } else if (auto ctor = dyn_cast<ConstructorDecl>(func)) { auto *dc = ctor->getDeclContext(); funcTy = dc->getSelfInterfaceType(); if (!funcTy) funcTy = ErrorType::get(Context); // 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) { SmallVector<AnyFunctionType::Param, 4> argTy; SmallVector<AnyFunctionType::Param, 4> initArgTy; if (i == e-1 && hasSelf) { // Substitute in our own 'self' parameter. argTy.push_back(computeSelfParam(func)); if (initFuncTy) { initArgTy.push_back(computeSelfParam(func, /*isInitializingCtor=*/true)); } } else { AnyFunctionType::decomposeInput(paramLists[e - i - 1]->getInterfaceType(Context), argTy); if (initFuncTy) initArgTy = argTy; } // 'throws' only applies to the innermost function. AnyFunctionType::ExtInfo info; if (i == 0 && func->hasThrows()) info = info.withThrows(); assert(std::all_of(argTy.begin(), argTy.end(), [](const AnyFunctionType::Param &aty){ return !aty.getType()->hasArchetype(); })); assert(!funcTy->hasArchetype()); if (initFuncTy) assert(!initFuncTy->hasArchetype()); if (sig && i == e-1) { 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); // We get bogus errors here with generic subscript materializeForSet. if (!isa<FuncDecl>(func) || cast<FuncDecl>(func)->getAccessorKind() != AccessorKind::IsMaterializeForSet) checkReferencedGenericParams(func, sig, *this); }
void TypeChecker::configureInterfaceType(AbstractFunctionDecl *func, GenericSignature *sig) { 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)) { auto *dc = ctor->getDeclContext(); funcTy = dc->getSelfInterfaceType(); // 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]->getInterfaceType(func->getDeclContext()); if (initFuncTy) initArgTy = argTy; } // 'throws' only applies to the innermost function. AnyFunctionType::ExtInfo info; if (i == 0 && func->hasThrows()) info = info.withThrows(); assert(!argTy->hasArchetype()); assert(!funcTy->hasArchetype()); if (initFuncTy) assert(!initFuncTy->hasArchetype()); if (sig && i == e-1) { 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); if (func->getGenericParams()) { // Collect all generic params referenced in parameter types, // return type or requirements. SmallPtrSet<GenericTypeParamDecl *, 4> referencedGenericParams; auto visitorFn = [&referencedGenericParams](Type t) { if (auto *paramTy = t->getAs<GenericTypeParamType>()) referencedGenericParams.insert(paramTy->getDecl()); }; funcTy->castTo<AnyFunctionType>()->getInput().visit(visitorFn); funcTy->castTo<AnyFunctionType>()->getResult().visit(visitorFn); 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(visitorFn); right.visit(visitorFn); } } // 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(); } } } }