@@ -1695,6 +1695,39 @@ static void diagnoseWrittenPlaceholderTypes(ASTContext &Ctx,
16951695 }
16961696}
16971697
1698+ // / Make sure that every protocol conformance requirement on 'Self' is
1699+ // / directly stated in the protocol's inheritance clause.
1700+ // /
1701+ // / This disallows protocol declarations where a conformance requirement on
1702+ // / 'Self' is implied by some other requirement, such as this:
1703+ // /
1704+ // / protocol Other { ... }
1705+ // / protocol Foo { associatedtype A : Other }
1706+ // / protocol Bar {
1707+ // / associatedtype A : Foo where Self == A.A
1708+ // / }
1709+ // /
1710+ // / Since name lookup is upstream of generic signature computation, we
1711+ // / want 'Other' to appear in the inheritance clause of 'Bar', so that
1712+ // / name lookup on Bar can find members of Other.
1713+ static void checkProtocolRefinementRequirements (ProtocolDecl *proto) {
1714+ auto requiredProtos = proto->getGenericSignature ()->getRequiredProtocols (
1715+ proto->getSelfInterfaceType ());
1716+
1717+ for (auto *otherProto : requiredProtos) {
1718+ // Every protocol 'P' has an implied requirement 'Self : P'; skip it.
1719+ if (otherProto == proto)
1720+ continue ;
1721+
1722+ // GenericSignature::getRequiredProtocols() canonicalizes the protocol
1723+ // list by dropping protocols that are inherited by other protocols in
1724+ // the list. Any protocols that remain in the list other than 'proto'
1725+ // itself are implied by a conformance requirement on 'Self', but are
1726+ // not (transitively) inherited by 'proto'.
1727+ proto->diagnose (diag::missing_protocol_refinement, proto, otherProto);
1728+ }
1729+ }
1730+
16981731namespace {
16991732class DeclChecker : public DeclVisitor <DeclChecker> {
17001733public:
@@ -2670,6 +2703,11 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
26702703
26712704 checkInheritanceClause (PD);
26722705
2706+ if (PD->getASTContext ().LangOpts .RequirementMachineProtocolSignatures
2707+ == RequirementMachineMode::Enabled) {
2708+ checkProtocolRefinementRequirements (PD);
2709+ }
2710+
26732711 TypeChecker::checkDeclCircularity (PD);
26742712 if (PD->isResilient ())
26752713 if (!SF || SF->Kind != SourceFileKind::Interface)
0 commit comments