Skip to content

Commit a81ec0a

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 80f062e commit a81ec0a

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
@@ -6613,6 +6613,47 @@ bool ProtocolDecl::inheritsFrom(const ProtocolDecl *super) const {
66136613
});
66146614
}
66156615

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

66376678
// Otherwise, check to see if there's an inverse on this protocol.
6638-
switch (proto->getMarking(ip).getInverse().getKind()) {
6639-
case InverseMarking::Kind::None:
6640-
return TypeWalker::Action::Stop; // No inverse, so implicitly inherited.
6641-
6642-
case InverseMarking::Kind::LegacyExplicit:
6643-
case InverseMarking::Kind::Explicit:
6644-
case InverseMarking::Kind::Inferred:
6645-
// The implicit requirement was suppressed on this protocol, keep looking.
6679+
6680+
// The implicit requirement was suppressed on this protocol, keep looking.
6681+
if (hasInverseMarking(proto, ip))
66466682
return TypeWalker::Action::Continue;
6647-
}
6683+
6684+
return TypeWalker::Action::Stop; // No inverse, so implicitly inherited.
66486685
});
66496686
}
66506687

0 commit comments

Comments
 (0)