Skip to content

Commit ecce9d2

Browse files
committed
RequirementMachine: Narrower definition of Rule::isProtocolRefinementRule()
With this change the RequirementMachine's minimization behavior with protocol refinement rules matches the GenericSignatureBuilder. See swiftlang#37466 for a full explanation of what's going on here.
1 parent a4e848f commit ecce9d2

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,28 @@ bool Rule::isIdentityConformanceRule() const {
6767
/// If this is a rule of the form [P].[Q] => [P] where [P] and [Q] are
6868
/// protocol symbols, return true, otherwise return false.
6969
bool Rule::isProtocolRefinementRule() const {
70-
return (LHS.size() == 2 &&
71-
RHS.size() == 1 &&
72-
LHS[0] == RHS[0] &&
73-
LHS[0].getKind() == Symbol::Kind::Protocol &&
74-
LHS[1].getKind() == Symbol::Kind::Protocol &&
75-
LHS[0] != LHS[1]);
70+
if (LHS.size() == 2 &&
71+
RHS.size() == 1 &&
72+
LHS[0] == RHS[0] &&
73+
LHS[0].getKind() == Symbol::Kind::Protocol &&
74+
LHS[1].getKind() == Symbol::Kind::Protocol &&
75+
LHS[0] != LHS[1]) {
76+
77+
// A protocol refinement rule only if it comes from a directly-stated
78+
// inheritance clause entry. It can only become redundant if it is
79+
// written in terms of other protocol refinement rules; otherwise, it
80+
// must appear in the protocol's requirement signature.
81+
//
82+
// See RewriteSystem::isValidRefinementPath().
83+
auto *proto = LHS[0].getProtocol();
84+
auto *otherProto = LHS[1].getProtocol();
85+
86+
auto inherited = proto->getInheritedProtocols();
87+
return (std::find(inherited.begin(), inherited.end(), otherProto)
88+
!= inherited.end());
89+
}
90+
91+
return false;
7692
}
7793

7894
/// Returns the length of the left hand side.
Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
// RUN: %target-typecheck-verify-swift
2-
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | %FileCheck %s
2+
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures -requirement-machine-protocol-signatures=verify %s 2>&1 | %FileCheck %s
33

44
protocol Base {}
5+
6+
// CHECK-LABEL: redundant_protocol_refinement.(file).Base@
7+
// CHECK-LABEL: Requirement signature: <Self>
8+
59
protocol Middle : Base {}
10+
11+
// CHECK-LABEL: redundant_protocol_refinement.(file).Middle@
12+
// CHECK-LABEL: Requirement signature: <Self where Self : Base>
13+
614
protocol Derived : Middle, Base {}
715
// expected-note@-1 {{conformance constraint 'Self' : 'Base' implied here}}
816
// expected-warning@-2 {{redundant conformance constraint 'Self' : 'Base'}}
917

18+
// CHECK-LABEL: redundant_protocol_refinement.(file).Derived@
19+
// CHECK-LABEL: Requirement signature: <Self where Self : Middle>
20+
1021
protocol P1 {}
1122

1223
protocol P2 {
@@ -15,10 +26,14 @@ protocol P2 {
1526

1627
// no warning here
1728
protocol Good: P2, P1 where Assoc == Self {}
29+
30+
// CHECK-LABEL: redundant_protocol_refinement.(file).Good@
1831
// CHECK-LABEL: Requirement signature: <Self where Self : P1, Self : P2, Self == Self.Assoc>
1932

2033
// missing refinement of 'P1'
2134
protocol Bad: P2 where Assoc == Self {}
2235
// expected-warning@-1 {{protocol 'Bad' should be declared to refine 'P1' due to a same-type constraint on 'Self'}}
2336
// expected-note@-2 {{conformance constraint 'Self' : 'P1' implied here}}
37+
38+
// CHECK-LABEL: redundant_protocol_refinement.(file).Bad@
2439
// CHECK-LABEL: Requirement signature: <Self where Self : P2, Self == Self.Assoc>

0 commit comments

Comments
 (0)