Skip to content

Commit 5736167

Browse files
authored
Merge pull request #42187 from slavapestov/rqm-diagnose-protocol-refinement
Sema: Diagnose missing entries in protocol inheritance clause when requirement machine is enabled
2 parents bf5b50a + a0b180f commit 5736167

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
16981731
namespace {
16991732
class DeclChecker : public DeclVisitor<DeclChecker> {
17001733
public:
@@ -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)

test/Generics/rdar51908331.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ protocol PH {
3232
}
3333

3434
protocol PI {
35+
// expected-warning@-1 {{protocol 'PI' should be declared to refine 'Decodable' due to a same-type constraint on 'Self'}}
36+
// expected-warning@-2 {{protocol 'PI' should be declared to refine 'Encodable' due to a same-type constraint on 'Self'}}
37+
// expected-warning@-3 {{protocol 'PI' should be declared to refine 'Hashable' due to a same-type constraint on 'Self'}}
38+
// expected-warning@-4 {{protocol 'PI' should be declared to refine 'SIMDScalar' due to a same-type constraint on 'Self'}}
3539
associatedtype A8 where A8.A7 == Self // expected-warning {{redundant same-type constraint 'Self.A8.A7' == 'Self'}}
3640
associatedtype A9 where A9.A7 == Self, A9.A8 == A8
3741
associatedtype A10 where A10.A7 == Self, A10.A8 == A8, A10.A9 == A9 // expected-warning {{redundant same-type constraint 'Self.A10.A7' == 'Self'}}

test/Generics/redundant_protocol_refinement.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
2-
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures -requirement-machine-protocol-signatures=verify %s 2>&1 | %FileCheck %s
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on
2+
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures -requirement-machine-protocol-signatures=on %s 2>&1 | %FileCheck %s
33

44
// CHECK-LABEL: redundant_protocol_refinement.(file).Base@
55
// CHECK-LABEL: Requirement signature: <Self>
@@ -12,8 +12,7 @@ protocol Middle : Base {}
1212
// CHECK-LABEL: redundant_protocol_refinement.(file).Derived@
1313
// CHECK-LABEL: Requirement signature: <Self where Self : Middle>
1414
protocol Derived : Middle, Base {}
15-
// expected-note@-1 {{conformance constraint 'Self' : 'Base' implied here}}
16-
// expected-warning@-2 {{redundant conformance constraint 'Self' : 'Base'}}
15+
// expected-warning@-1 {{redundant conformance constraint 'Self' : 'Base'}}
1716

1817
// CHECK-LABEL: redundant_protocol_refinement.(file).Derived2@
1918
// CHECK-LABEL: Requirement signature: <Self where Self : Middle>
@@ -22,8 +21,7 @@ protocol Derived2 : Middle {}
2221
// CHECK-LABEL: redundant_protocol_refinement.(file).MoreDerived@
2322
// CHECK-LABEL: Requirement signature: <Self where Self : Derived2>
2423
protocol MoreDerived : Derived2, Base {}
25-
// expected-note@-1 {{conformance constraint 'Self' : 'Base' implied here}}
26-
// expected-warning@-2 {{redundant conformance constraint 'Self' : 'Base'}}
24+
// expected-warning@-1 {{redundant conformance constraint 'Self' : 'Base'}}
2725

2826
protocol P1 {}
2927

@@ -40,7 +38,6 @@ protocol Good: P2, P1 where Assoc == Self {}
4038
// missing refinement of 'P1'
4139
protocol Bad: P2 where Assoc == Self {}
4240
// expected-warning@-1 {{protocol 'Bad' should be declared to refine 'P1' due to a same-type constraint on 'Self'}}
43-
// expected-note@-2 {{conformance constraint 'Self' : 'P1' implied here}}
4441

4542
// CHECK-LABEL: redundant_protocol_refinement.(file).Bad@
4643
// CHECK-LABEL: Requirement signature: <Self where Self : P2, Self == Self.[P2]Assoc>

0 commit comments

Comments
 (0)