Skip to content

Commit 09ab12d

Browse files
committed
[AST] Simplify ProtocolDecl::requiresInvertible check
The method only needs to know about the presence of inverses for the given invertiable protocol.
1 parent b51600d commit 09ab12d

File tree

1 file changed

+46
-9
lines changed

1 file changed

+46
-9
lines changed

lib/AST/Decl.cpp

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6614,6 +6614,47 @@ bool ProtocolDecl::inheritsFrom(const ProtocolDecl *super) const {
66146614
});
66156615
}
66166616

6617+
static bool hasInverseMarking(ProtocolDecl *P, InvertibleProtocolKind target) {
6618+
auto &ctx = P->getASTContext();
6619+
6620+
// Legacy support stops here.
6621+
if (!ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics))
6622+
return false;
6623+
6624+
auto inheritedTypes = P->getInherited();
6625+
for (unsigned i = 0; i < inheritedTypes.size(); ++i) {
6626+
auto type = inheritedTypes.getResolvedType(i, TypeResolutionStage::Structural);
6627+
if (!type)
6628+
continue;
6629+
6630+
if (auto *composition = type->getAs<ProtocolCompositionType>()) {
6631+
// Found ~<target> in the protocol inheritance clause.
6632+
if (composition->getInverses().contains(target))
6633+
return true;
6634+
}
6635+
}
6636+
6637+
auto *whereClause = P->getTrailingWhereClause();
6638+
if (!whereClause)
6639+
return false;
6640+
6641+
return llvm::any_of(
6642+
whereClause->getRequirements(), [&](const RequirementRepr &reqRepr) {
6643+
if (reqRepr.isInvalid() ||
6644+
reqRepr.getKind() != RequirementReprKind::TypeConstraint)
6645+
return false;
6646+
6647+
auto *subjectRepr = dyn_cast<IdentTypeRepr>(reqRepr.getSubjectRepr());
6648+
auto *constraintRepr = reqRepr.getConstraintRepr();
6649+
6650+
if (!subjectRepr ||
6651+
!subjectRepr->getNameRef().isSimpleName(ctx.Id_Self))
6652+
return false;
6653+
6654+
return constraintRepr->isInverseOf(target, P->getDeclContext());
6655+
});
6656+
}
6657+
66176658
bool ProtocolDecl::requiresInvertible(InvertibleProtocolKind ip) const {
66186659
// Protocols don't inherit from themselves.
66196660
if (auto thisIP = getInvertibleProtocolKind()) {
@@ -6641,16 +6682,12 @@ bool ProtocolDecl::requiresInvertible(InvertibleProtocolKind ip) const {
66416682
return TypeWalker::Action::Continue;
66426683

66436684
// Otherwise, check to see if there's an inverse on this protocol.
6644-
switch (proto->getMarking(ip).getInverse().getKind()) {
6645-
case InverseMarking::Kind::None:
6646-
return TypeWalker::Action::Stop; // No inverse, so implicitly inherited.
6647-
6648-
case InverseMarking::Kind::LegacyExplicit:
6649-
case InverseMarking::Kind::Explicit:
6650-
case InverseMarking::Kind::Inferred:
6651-
// The implicit requirement was suppressed on this protocol, keep looking.
6685+
6686+
// The implicit requirement was suppressed on this protocol, keep looking.
6687+
if (hasInverseMarking(proto, ip))
66526688
return TypeWalker::Action::Continue;
6653-
}
6689+
6690+
return TypeWalker::Action::Stop; // No inverse, so implicitly inherited.
66546691
});
66556692
}
66566693

0 commit comments

Comments
 (0)