Skip to content

Commit 44dac01

Browse files
committed
GSB: Fix getMinimalConformanceSource() for top-level requirements in a requirement signature
Consider the following program: protocol P1 { associatedtype A : P2 } protocol P2 { associatedtype A } func f<T>(_: T) where T : P2, T.A : P1, T.A.A == T {} There are two proofs of T : P2: - The explicit requirement in f()'s generic signature. - Since T.A.A == T, we can also prove T : P2 via T.A.A : P2: - First, we prove that T.A : P1 via the explicit requirement in f()'s generic signature. - Second, we prove that T.A.A : P1 via Self.A : P2 in P1's requirement signature. However, the second proof does not render the explicit requirement T : P2 redundant, because it relies on the existence of the nested type T.A, which only exists if T : P2. This is captured in getMinimalConformanceSource(), which returns nullptr for the requirement source corresponding to the second proof above. It does this by looking at the root type of the requirement source, T.A. Now consider the analogous situation but with protocols -- let's replace f() with a protocol P3: protocol P3 : P2 where Self.A : P1, Self.A.A == Self {} Here, we also have two proofs of Self : P2: - The explicit requirement in P3's requirement signature. - First, we prove that Self.A : P1 via the explicit requirement in P3's requirement siganture. - Second, we prove that Self.A.A : P1 via Self.A : P2 in P1's requirement signature. Once again, the second proof implicitly depends on the explicit requirement, so we cannot use it to mark the explicit requirement as redundant. However, since the requirement source root type here is just 'Self', we were unable to recognize this, and we would diagnose the requirement as redundant and drop it, resulting in computing an invalid requirement signature for protocol P3. To fix this, handle requirements at the top level of a protocol requirement signature just like they are explicit requirements. Fixes https://bugs.swift.org/browse/SR-13850 / rdar://problem/71377571.
1 parent cd724d4 commit 44dac01

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,19 @@ const RequirementSource *RequirementSource::getMinimalConformanceSource(
820820
switch (source->kind) {
821821
case ProtocolRequirement:
822822
case InferredProtocolRequirement: {
823+
// Special handling for top-level requirement signature requirements;
824+
// pretend the root type is the subject type as written in the
825+
// protocol, and not 'Self', so that we can consider this requirement
826+
// self-derived if it depends on one of the conformances that make
827+
// the root type valid.
828+
if (requirementSignatureSelfProto) {
829+
if (source->getProtocolDecl() == requirementSignatureSelfProto &&
830+
source->parent->kind == RequirementSource::RequirementSignatureSelf) {
831+
rootType = source->getAffectedType();
832+
return false;
833+
}
834+
}
835+
823836
// Note that we've seen a protocol requirement.
824837
sawProtocolRequirement = true;
825838

test/Generics/sr13850.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-typecheck-verify-swift -debug-generic-signatures 2>&1 | %FileCheck %s
2+
3+
// https://bugs.swift.org/browse/SR-13850
4+
5+
// CHECK: Requirement signature: <Self where Self.A : P2>
6+
protocol P1 {
7+
associatedtype A: P2
8+
}
9+
10+
// CHECK: Requirement signature: <Self>
11+
protocol P2 {
12+
associatedtype A
13+
}
14+
15+
// Neither one of 'P3', 'P4' or 'f()' should have diagnosed
16+
// redundant conformance requirements.
17+
18+
// CHECK: Requirement signature: <Self where Self : P2, Self == Self.A.A, Self.A : P1>
19+
protocol P3 : P2 where Self.A: P1, Self.A.A == Self { }
20+
21+
// CHECK: Requirement signature: <Self where Self.X : P2, Self.X == Self.X.A.A, Self.X.A : P1>
22+
protocol P4 {
23+
associatedtype X where X : P2, X.A: P1, X.A.A == X
24+
}
25+
26+
// CHECK: Generic signature: <T where T : P2, T == T.A.A, T.A : P1>
27+
func f<T : P2>(_: T) where T.A : P1, T.A.A == T { }

0 commit comments

Comments
 (0)