Sema: Re-organize BindingSet::finalize()

This commit is contained in:
Slava Pestov
2025-11-13 18:03:36 -05:00
parent 5f2db0c96c
commit 53d802a239

View File

@@ -665,43 +665,46 @@ static Type getKeyPathType(ASTContext &ctx, KeyPathCapability capability,
}
bool BindingSet::finalize(bool transitive) {
if (transitive)
if (transitive) {
inferTransitiveBindings();
if (auto *locator = TypeVar->getImpl().getLocator()) {
if (locator->isLastElement<LocatorPathElt::MemberRefBase>()) {
// If this is a base of an unresolved member chain, as a last
// resort effort let's infer base to be a protocol type based
// on contextual conformance requirements.
//
// This allows us to find solutions in cases like this:
//
// \code
// func foo<T: P>(_: T) {}
// foo(.bar) <- `.bar` should be a static member of `P`.
// \endcode
if (transitive && !hasViableBindings()) {
inferTransitiveProtocolRequirements();
if (!hasViableBindings()) {
if (auto *locator = TypeVar->getImpl().getLocator()) {
if (locator->isLastElement<LocatorPathElt::MemberRefBase>()) {
// If this is a base of an unresolved member chain, as a last
// resort effort let's infer base to be a protocol type based
// on contextual conformance requirements.
//
// This allows us to find solutions in cases like this:
//
// \code
// func foo<T: P>(_: T) {}
// foo(.bar) <- `.bar` should be a static member of `P`.
// \endcode
inferTransitiveProtocolRequirements();
if (TransitiveProtocols.has_value()) {
for (auto *constraint : *TransitiveProtocols) {
Type protocolTy = constraint->getSecondType();
if (TransitiveProtocols.has_value()) {
for (auto *constraint : *TransitiveProtocols) {
Type protocolTy = constraint->getSecondType();
// Compiler-known marker protocols cannot be extended with members,
// so do not consider them.
if (auto p = protocolTy->getAs<ProtocolType>()) {
if (ProtocolDecl *decl = p->getDecl())
if (decl->getKnownProtocolKind() && decl->isMarkerProtocol())
continue;
// Compiler-known marker protocols cannot be extended with members,
// so do not consider them.
if (auto p = protocolTy->getAs<ProtocolType>()) {
if (ProtocolDecl *decl = p->getDecl())
if (decl->getKnownProtocolKind() && decl->isMarkerProtocol())
continue;
}
addBinding({protocolTy, AllowedBindingKind::Exact, constraint},
/*isTransitive=*/false);
}
addBinding({protocolTy, AllowedBindingKind::Exact, constraint},
/*isTransitive=*/false);
}
}
}
}
}
if (auto *locator = TypeVar->getImpl().getLocator()) {
if (TypeVar->getImpl().isKeyPathType()) {
auto &ctx = CS.getASTContext();