本文整理汇总了C++中TypeChecker::diagnose方法的典型用法代码示例。如果您正苦于以下问题:C++ TypeChecker::diagnose方法的具体用法?C++ TypeChecker::diagnose怎么用?C++ TypeChecker::diagnose使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TypeChecker
的用法示例。
在下文中一共展示了TypeChecker::diagnose方法的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1:
static InFlightDiagnostic
diagnoseTypoCorrection(TypeChecker &tc, DeclNameLoc loc, ValueDecl *decl) {
if (auto var = dyn_cast<VarDecl>(decl)) {
// Suggest 'self' at the use point instead of pointing at the start
// of the function.
if (var->isSelfParameter())
return tc.diagnose(loc.getBaseNameLoc(), diag::note_typo_candidate,
decl->getName().str());
}
if (!decl->getLoc().isValid() && decl->getDeclContext()->isTypeContext()) {
Decl *parentDecl = dyn_cast<ExtensionDecl>(decl->getDeclContext());
if (!parentDecl) parentDecl = cast<NominalTypeDecl>(decl->getDeclContext());
if (parentDecl->getLoc().isValid()) {
StringRef kind = (isa<VarDecl>(decl) ? "property" :
isa<ConstructorDecl>(decl) ? "initializer" :
isa<FuncDecl>(decl) ? "method" :
"member");
return tc.diagnose(parentDecl, diag::note_typo_candidate_implicit_member,
decl->getName().str(), kind);
}
}
return tc.diagnose(decl, diag::note_typo_candidate, decl->getName().str());
}
示例2: deriveCaseIterable
Type DerivedConformance::deriveCaseIterable(TypeChecker &tc, Decl *parentDecl,
NominalTypeDecl *targetDecl,
AssociatedTypeDecl *assocType) {
// Conformance can't be synthesized in an extension.
auto caseIterableProto
= tc.Context.getProtocol(KnownProtocolKind::CaseIterable);
auto caseIterableType = caseIterableProto->getDeclaredType();
if (targetDecl != parentDecl) {
tc.diagnose(parentDecl->getLoc(), diag::cannot_synthesize_in_extension,
caseIterableType);
return nullptr;
}
// We can only synthesize CaseIterable for enums.
auto enumDecl = dyn_cast<EnumDecl>(targetDecl);
if (!enumDecl)
return nullptr;
// Check that we can actually derive CaseIterable for this type.
if (!canDeriveConformance(targetDecl))
return nullptr;
if (assocType->getName() == tc.Context.Id_AllCases) {
return deriveCaseIterable_AllCases(tc, parentDecl, enumDecl);
}
tc.diagnose(assocType->getLoc(),
diag::broken_case_iterable_requirement);
return nullptr;
}
示例3:
static InFlightDiagnostic
diagnoseTypoCorrection(TypeChecker &tc, DeclNameLoc loc, ValueDecl *decl) {
if (auto var = dyn_cast<VarDecl>(decl)) {
// Suggest 'self' at the use point instead of pointing at the start
// of the function.
if (var->isSelfParameter())
return tc.diagnose(loc.getBaseNameLoc(), diag::note_typo_candidate,
decl->getName().str());
}
return tc.diagnose(decl, diag::note_typo_candidate, decl->getName().str());
}
示例4: hasValidCodingKeysEnum
/// Returns whether the given type has a valid nested \c CodingKeys enum.
///
/// If the type has an invalid \c CodingKeys entity, produces diagnostics to
/// complain about the error. In this case, the error result will be true -- in
/// the case where we don't have a valid CodingKeys enum and have produced
/// diagnostics here, we don't want to then attempt to synthesize a CodingKeys
/// enum.
///
/// \param tc The typechecker to use in validating {En,Decodable} conformance.
///
/// \param target The type decl whose nested \c CodingKeys type to validate.
///
/// \param proto The {En,De}codable protocol to ensure the properties matching
/// the keys conform to.
///
/// \returns A \c CodingKeysValidity value representing the result of the check.
static CodingKeysValidity hasValidCodingKeysEnum(TypeChecker &tc,
NominalTypeDecl *target,
ProtocolDecl *proto) {
auto &C = tc.Context;
auto codingKeysDecls = target->lookupDirect(DeclName(C.Id_CodingKeys));
if (codingKeysDecls.empty())
return CodingKeysValidity(/*hasType=*/false, /*isValid=*/true);
// Only ill-formed code would produce multiple results for this lookup.
// This would get diagnosed later anyway, so we're free to only look at the
// first result here.
auto result = codingKeysDecls.front();
auto *codingKeysTypeDecl = dyn_cast<TypeDecl>(result);
if (!codingKeysTypeDecl) {
tc.diagnose(result->getLoc(),
diag::codable_codingkeys_type_is_not_an_enum_here,
proto->getDeclaredType());
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
}
// CodingKeys may be a typealias. If so, follow the alias to its canonical
// type.
auto codingKeysType = codingKeysTypeDecl->getDeclaredInterfaceType();
if (isa<TypeAliasDecl>(codingKeysTypeDecl)) {
codingKeysTypeDecl = codingKeysType->getAnyNominal();
}
// Ensure that the type we found conforms to the CodingKey protocol.
auto *codingKeyProto = C.getProtocol(KnownProtocolKind::CodingKey);
if (!tc.conformsToProtocol(codingKeysType, codingKeyProto,
target->getDeclContext(),
ConformanceCheckFlags::Used)) {
tc.diagnose(codingKeysTypeDecl->getLoc(),
diag::codable_codingkeys_type_does_not_conform_here,
proto->getDeclaredType());
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
}
// CodingKeys must be an enum for synthesized conformance.
auto *codingKeysEnum = dyn_cast<EnumDecl>(codingKeysTypeDecl);
if (!codingKeysEnum) {
tc.diagnose(codingKeysTypeDecl->getLoc(),
diag::codable_codingkeys_type_is_not_an_enum_here,
proto->getDeclaredType());
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/false);
}
bool valid = validateCodingKeysEnum(tc, codingKeysEnum, target, proto);
return CodingKeysValidity(/*hasType=*/true, /*isValid=*/valid);
}
示例5: deriveRawRepresentable
Type DerivedConformance::deriveRawRepresentable(TypeChecker &tc,
Decl *parentDecl,
NominalTypeDecl *type,
AssociatedTypeDecl *assocType) {
// Check preconditions. These should already have been diagnosed by
// type-checking but we may still get here after recovery.
// The type must be an enum.
auto enumDecl = dyn_cast<EnumDecl>(type);
if (!enumDecl)
return nullptr;
// It must have a valid raw type.
if (!enumDecl->hasRawType())
return nullptr;
if (!enumDecl->getInherited().empty() &&
enumDecl->getInherited().front().isError())
return nullptr;
// There must be enum elements.
if (enumDecl->getAllElements().empty())
return nullptr;
for (auto elt : enumDecl->getAllElements())
tc.validateDecl(elt);
if (assocType->getName() == tc.Context.Id_RawValue) {
return deriveRawRepresentable_Raw(tc, parentDecl, enumDecl);
}
tc.diagnose(assocType->getLoc(),
diag::broken_raw_representable_requirement);
return nullptr;
}
示例6: offerDefaultValueUnwrapFixit
// Suggest a default value via ?? <default value>
static void offerDefaultValueUnwrapFixit(TypeChecker &TC, DeclContext *DC, Expr *expr) {
auto diag =
TC.diagnose(expr->getLoc(), diag::unwrap_with_default_value);
// Figure out what we need to parenthesize.
bool needsParensInside =
exprNeedsParensBeforeAddingNilCoalescing(TC, DC, expr);
bool needsParensOutside =
exprNeedsParensAfterAddingNilCoalescing(TC, DC, expr, expr);
llvm::SmallString<2> insertBefore;
llvm::SmallString<32> insertAfter;
if (needsParensOutside) {
insertBefore += "(";
}
if (needsParensInside) {
insertBefore += "(";
insertAfter += ")";
}
insertAfter += " ?? <" "#default value#" ">";
if (needsParensOutside)
insertAfter += ")";
if (!insertBefore.empty()) {
diag.fixItInsert(expr->getStartLoc(), insertBefore);
}
diag.fixItInsertAfter(expr->getEndLoc(), insertAfter);
}
示例7: getInfixData
/// getInfixData - If the specified expression is an infix binary
/// operator, return its infix operator attributes.
static InfixData getInfixData(TypeChecker &TC, DeclContext *DC, Expr *E) {
if (auto *ifExpr = dyn_cast<IfExpr>(E)) {
// Ternary has fixed precedence.
assert(!ifExpr->isFolded() && "already folded if expr in sequence?!");
(void)ifExpr;
return InfixData(IntrinsicPrecedences::IfExpr,
Associativity::Right,
/*assignment*/ false);
}
if (auto *assign = dyn_cast<AssignExpr>(E)) {
// Assignment has fixed precedence.
assert(!assign->isFolded() && "already folded assign expr in sequence?!");
(void)assign;
return InfixData(IntrinsicPrecedences::AssignExpr,
Associativity::Right,
/*assignment*/ true);
}
if (auto *as = dyn_cast<ExplicitCastExpr>(E)) {
// 'as' and 'is' casts have fixed precedence.
assert(!as->isFolded() && "already folded 'as' expr in sequence?!");
(void)as;
return InfixData(IntrinsicPrecedences::ExplicitCastExpr,
Associativity::None,
/*assignment*/ false);
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
SourceFile *SF = DC->getParentSourceFile();
Identifier name = DRE->getDecl()->getName();
bool isCascading = DC->isCascadingContextForLookup(true);
if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading,
E->getLoc()))
return op->getInfixData();
}
if (OverloadedDeclRefExpr *OO = dyn_cast<OverloadedDeclRefExpr>(E)) {
SourceFile *SF = DC->getParentSourceFile();
Identifier name = OO->getDecls()[0]->getName();
bool isCascading = DC->isCascadingContextForLookup(true);
if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading,
E->getLoc()))
return op->getInfixData();
}
// If E is already an ErrorExpr, then we've diagnosed it as invalid already,
// otherwise emit an error.
if (!isa<ErrorExpr>(E))
TC.diagnose(E->getLoc(), diag::unknown_binop);
// Recover with an infinite-precedence left-associative operator.
return InfixData((unsigned char)~0U, Associativity::Left,
/*assignment*/ false);
}
示例8: InFlightDiagnostic
static InFlightDiagnostic
noteTypoCorrection(TypeChecker &tc, DeclNameLoc loc, ValueDecl *decl,
bool wasClaimed) {
if (auto var = dyn_cast<VarDecl>(decl)) {
// Suggest 'self' at the use point instead of pointing at the start
// of the function.
if (var->isSelfParameter()) {
if (wasClaimed) {
// We don't need an extra note for this case because the programmer
// knows what 'self' refers to.
return InFlightDiagnostic();
}
return tc.diagnose(loc.getBaseNameLoc(), diag::note_typo_candidate,
var->getName().str());
}
}
if (Decl *parentDecl = findExplicitParentForImplicitDecl(decl)) {
StringRef kind = (isa<VarDecl>(decl) ? "property" :
isa<ConstructorDecl>(decl) ? "initializer" :
isa<FuncDecl>(decl) ? "method" :
"member");
return tc.diagnose(parentDecl,
wasClaimed ? diag::implicit_member_declared_here
: diag::note_typo_candidate_implicit_member,
decl->getBaseName().userFacingName(), kind);
}
if (wasClaimed) {
return tc.diagnose(decl, diag::decl_declared_here, decl->getBaseName());
} else {
return tc.diagnose(decl, diag::note_typo_candidate,
decl->getBaseName().userFacingName());
}
}
示例9: canSynthesizeRawRepresentable
static bool canSynthesizeRawRepresentable(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) {
// It must have a valid raw type.
Type rawType = enumDecl->getRawType();
if (!rawType)
return false;
auto parentDC = cast<DeclContext>(parentDecl);
rawType = ArchetypeBuilder::mapTypeIntoContext(parentDC, rawType);
if (!enumDecl->getInherited().empty() &&
enumDecl->getInherited().front().isError())
return false;
// The raw type must be Equatable, so that we have a suitable ~= for synthesized switch statements.
auto equatableProto = tc.getProtocol(enumDecl->getLoc(),
KnownProtocolKind::Equatable);
if (!equatableProto)
return false;
if (!tc.conformsToProtocol(rawType, equatableProto, enumDecl, None)) {
SourceLoc loc = enumDecl->getInherited()[0].getSourceRange().Start;
tc.diagnose(loc, diag::enum_raw_type_not_equatable, rawType);
return false;
}
// There must be enum elements.
if (enumDecl->getAllElements().empty())
return false;
// Have the type-checker validate that:
// - the enum elements all have the same type
// - they all match the enum type
for (auto elt : enumDecl->getAllElements()) {
tc.validateDecl(elt);
if (elt->isInvalid()) {
return false;
}
}
// If it meets all of those requirements, we can synthesize RawRepresentable conformance.
return true;
}
示例10: deriveRawRepresentable
Type DerivedConformance::deriveRawRepresentable(TypeChecker &tc,
Decl *parentDecl,
NominalTypeDecl *type,
AssociatedTypeDecl *assocType) {
// We can only synthesize RawRepresentable for enums.
auto enumDecl = dyn_cast<EnumDecl>(type);
if (!enumDecl)
return nullptr;
// Check other preconditions for synthesized conformance.
if (!canSynthesizeRawRepresentable(tc, parentDecl, enumDecl))
return nullptr;
if (assocType->getName() == tc.Context.Id_RawValue) {
return deriveRawRepresentable_Raw(tc, parentDecl, enumDecl);
}
tc.diagnose(assocType->getLoc(),
diag::broken_raw_representable_requirement);
return nullptr;
}
示例11: checkProtocolSelfRequirements
// For a generic requirement in a protocol, make sure that the requirement
// set didn't add any requirements to Self or its associated types.
static bool checkProtocolSelfRequirements(GenericSignature *sig,
ValueDecl *decl,
TypeChecker &TC) {
// 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 (auto *proto = dyn_cast<ProtocolDecl>(decl->getDeclContext())) {
auto protoSelf = proto->getSelfInterfaceType();
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(protoSelf, req.getFirstType()) ||
!isSelfDerivedOrConcrete(protoSelf, 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;
TC.diagnose(decl,
TC.Context.LangOpts.EffectiveLanguageVersion[0] >= 4
? diag::requirement_restricts_self
: diag::requirement_restricts_self_swift3,
decl->getDescriptiveKind(), decl->getFullName(),
req.getFirstType().getString(),
static_cast<unsigned>(req.getKind()),
req.getSecondType().getString());
if (TC.Context.LangOpts.EffectiveLanguageVersion[0] >= 4)
return true;
}
}
return false;
}
示例12: varConformsToCodable
/// Validates the given CodingKeys enum decl by ensuring its cases are a 1-to-1
/// match with the stored vars of the given type.
///
/// \param tc The typechecker to use in validating {En,De}codable conformance.
///
/// \param codingKeysDecl The \c CodingKeys enum decl to validate.
///
/// \param target The nominal type decl to validate the \c CodingKeys against.
///
/// \param proto The {En,De}codable protocol to validate all the keys conform
/// to.
static bool
validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
NominalTypeDecl *target, ProtocolDecl *proto) {
// Look through all var decls in the given type.
// * Filter out lazy/computed vars (currently already done by
// getStoredProperties).
// * Filter out ones which are present in the given decl (by name).
//
// If any of the entries in the CodingKeys decl are not present in the type
// by name, then this decl doesn't match.
// If there are any vars left in the type which don't have a default value
// (for Decodable), then this decl doesn't match.
// Here we'll hold on to properties by name -- when we've validated a property
// against its CodingKey entry, it will get removed.
llvm::SmallDenseMap<Identifier, VarDecl *, 8> properties;
for (auto *varDecl : target->getStoredProperties(/*skipInaccessible=*/true)) {
properties[varDecl->getName()] = varDecl;
}
bool propertiesAreValid = true;
for (auto elt : codingKeysDecl->getAllElements()) {
auto it = properties.find(elt->getName());
if (it == properties.end()) {
tc.diagnose(elt->getLoc(), diag::codable_extraneous_codingkey_case_here,
elt->getName());
// TODO: Investigate typo-correction here; perhaps the case name was
// misspelled and we can provide a fix-it.
propertiesAreValid = false;
continue;
}
// We have a property to map to. Ensure it's {En,De}codable.
auto conformance = varConformsToCodable(tc, target->getDeclContext(),
it->second, proto);
switch (conformance) {
case Conforms:
// The property was valid. Remove it from the list.
properties.erase(it);
break;
case DoesNotConform:
tc.diagnose(it->second->getLoc(),
diag::codable_non_conforming_property_here,
proto->getDeclaredType(), it->second->getType());
LLVM_FALLTHROUGH;
case TypeNotValidated:
// We don't produce a diagnostic for a type which failed to validate.
// This will produce a diagnostic elsewhere anyway.
propertiesAreValid = false;
continue;
}
}
if (!propertiesAreValid)
return false;
// If there are any remaining properties which the CodingKeys did not cover,
// we can skip them on encode. On decode, though, we can only skip them if
// they have a default value.
if (!properties.empty() &&
proto == tc.Context.getProtocol(KnownProtocolKind::Decodable)) {
for (auto it = properties.begin(); it != properties.end(); ++it) {
if (it->second->getParentInitializer() != nullptr) {
// Var has a default value.
continue;
}
propertiesAreValid = false;
tc.diagnose(it->second->getLoc(), diag::codable_non_decoded_property_here,
proto->getDeclaredType(), it->first);
}
}
return propertiesAreValid;
}
示例13: bindExtensionDecl
static void bindExtensionDecl(ExtensionDecl *ED, TypeChecker &TC) {
if (ED->getExtendedType())
return;
// If we didn't parse a type, fill in an error type and bail out.
if (!ED->getExtendedTypeLoc().getTypeRepr()) {
ED->setInvalid();
ED->getExtendedTypeLoc().setInvalidType(TC.Context);
return;
}
auto dc = ED->getDeclContext();
// Validate the representation.
// FIXME: Perform some kind of "shallow" validation here?
TypeResolutionOptions options;
options |= TR_AllowUnboundGenerics;
options |= TR_ExtensionBinding;
if (TC.validateType(ED->getExtendedTypeLoc(), dc, options)) {
ED->setInvalid();
return;
}
// Dig out the extended type.
auto extendedType = ED->getExtendedType();
// Hack to allow extending a generic typealias.
if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
if (extendedNominal) {
extendedType = extendedNominal->getDeclaredType();
ED->getExtendedTypeLoc().setType(extendedType);
}
}
}
// Handle easy cases.
// Cannot extend a metatype.
if (extendedType->is<AnyMetatypeType>()) {
TC.diagnose(ED->getLoc(), diag::extension_metatype, extendedType)
.highlight(ED->getExtendedTypeLoc().getSourceRange());
ED->setInvalid();
ED->getExtendedTypeLoc().setInvalidType(TC.Context);
return;
}
// Cannot extend a bound generic type.
if (extendedType->isSpecialized()) {
TC.diagnose(ED->getLoc(), diag::extension_specialization,
extendedType->getAnyNominal()->getName())
.highlight(ED->getExtendedTypeLoc().getSourceRange());
ED->setInvalid();
ED->getExtendedTypeLoc().setInvalidType(TC.Context);
return;
}
// Dig out the nominal type being extended.
NominalTypeDecl *extendedNominal = extendedType->getAnyNominal();
if (!extendedNominal) {
TC.diagnose(ED->getLoc(), diag::non_nominal_extension, extendedType)
.highlight(ED->getExtendedTypeLoc().getSourceRange());
ED->setInvalid();
ED->getExtendedTypeLoc().setInvalidType(TC.Context);
return;
}
assert(extendedNominal && "Should have the nominal type being extended");
// If the extended type is generic or is a protocol. Clone or create
// the generic parameters.
if (extendedNominal->isGenericContext()) {
if (auto proto = dyn_cast<ProtocolDecl>(extendedNominal)) {
// For a protocol extension, build the generic parameter list.
ED->setGenericParams(proto->createGenericParams(ED));
} else {
// Clone the existing generic parameter list.
ED->setGenericParams(
cloneGenericParams(TC.Context, ED,
extendedNominal->getGenericParamsOfContext()));
}
}
// If we have a trailing where clause, deal with it now.
// For now, trailing where clauses are only permitted on protocol extensions.
if (auto trailingWhereClause = ED->getTrailingWhereClause()) {
if (!extendedNominal->isGenericContext()) {
// Only generic and protocol types are permitted to have
// trailing where clauses.
TC.diagnose(ED, diag::extension_nongeneric_trailing_where, extendedType)
.highlight(trailingWhereClause->getSourceRange());
ED->setTrailingWhereClause(nullptr);
} else {
// Merge the trailing where clause into the generic parameter list.
// FIXME: Long-term, we'd like clients to deal with the trailing where
// clause explicitly, but for now it's far more direct to represent
// the trailing where clause as part of the requirements.
ED->getGenericParams()->addTrailingWhereClause(
TC.Context,
trailingWhereClause->getWhereLoc(),
//.........这里部分代码省略.........
示例14: checkReferencedGenericParams
//.........这里部分代码省略.........
break;
}
// Collect generic parameter types referenced by types used in a requirement.
ReferencedGenericTypeWalker walker;
if (first && first->hasTypeParameter())
first.walk(walker);
if (second && second->hasTypeParameter())
second.walk(walker);
auto &genericParamsUsedByRequirementTypes =
walker.getReferencedGenericParams();
// If at least one of the collected generic types or a root generic
// parameter of dependent member types is known to be referenced by
// parameter types, return types or other types known to be "referenced",
// then all the types used in the requirement are considered to be
// referenced, because they are used to defined something that is known
// to be referenced.
bool foundNewReferencedGenericParam = false;
if (std::any_of(genericParamsUsedByRequirementTypes.begin(),
genericParamsUsedByRequirementTypes.end(),
[&referencedGenericParams](CanType t) {
assert(t->isTypeParameter());
return referencedGenericParams.find(
t->getRootGenericParam()
->getCanonicalType()) !=
referencedGenericParams.end();
})) {
std::for_each(genericParamsUsedByRequirementTypes.begin(),
genericParamsUsedByRequirementTypes.end(),
[&referencedGenericParams,
&foundNewReferencedGenericParam](CanType t) {
// Add only generic type parameters, but ignore any
// dependent member types, because requirement
// on a dependent member type does not provide enough
// information to infer the base generic type
// parameter.
if (!t->is<GenericTypeParamType>())
return;
if (referencedGenericParams.insert(t).second)
foundNewReferencedGenericParam = true;
});
}
return foundNewReferencedGenericParam;
};
ArrayRef<Requirement> requirements;
auto FindReferencedGenericParamsInRequirements = [&requirements, sig, &reqTypesVisitor] {
requirements = sig->getRequirements();
// Try to find new referenced generic parameter types in requirements until
// we reach a fix point. We need to iterate until a fix point, because we
// may have e.g. chains of same-type requirements like:
// not-yet-referenced-T1 == not-yet-referenced-T2.DepType2,
// not-yet-referenced-T2 == not-yet-referenced-T3.DepType3,
// not-yet-referenced-T3 == referenced-T4.DepType4.
// When we process the first of these requirements, we don't know yet that
// T2
// will be referenced, because T3 will be referenced,
// because T3 == T4.DepType4.
while (true) {
bool foundNewReferencedGenericParam = false;
for (auto req : requirements) {
if (reqTypesVisitor(req))
foundNewReferencedGenericParam = true;
}
if (!foundNewReferencedGenericParam)
break;
}
};
// Find the depth of the function's own generic parameters.
unsigned fnGenericParamsDepth = genericParams->getDepth();
// Check that every generic parameter type from the signature is
// among referencedGenericParams.
for (auto *genParam : sig->getGenericParams()) {
auto *paramDecl = genParam->getDecl();
if (paramDecl->getDepth() != fnGenericParamsDepth)
continue;
if (!referencedGenericParams.count(genParam->getCanonicalType())) {
// Lazily search for generic params that are indirectly used in the
// function signature. Do it only if there is a generic parameter
// that is not known to be referenced yet.
if (requirements.empty()) {
FindReferencedGenericParamsInRequirements();
// Nothing to do if this generic parameter is considered to be
// referenced after analyzing the requirements from the generic
// signature.
if (referencedGenericParams.count(genParam->getCanonicalType()))
continue;
}
// Produce an error that this generic parameter cannot be bound.
TC.diagnose(paramDecl->getLoc(), diag::unreferenced_generic_parameter,
paramDecl->getNameStr());
decl->setInterfaceType(ErrorType::get(TC.Context));
decl->setInvalid();
}
}
}