Skip to content

Commit 307aa46

Browse files
committed
RequirementMachine: Fix a case where we diagnose requirements made redundant by an inferred requirement
We infer requirements from types appearing in parameter and result types, like this: func foo<T>(_: Set<T>) // 'T : Hashable' inferred from 'Set<T>' Normally we muffle the warning if the requirement is re-stated redundantly: func foo<T>(_: Set<T>) where T : Hashable // no warning However, in some cases we failed to do this if the requirement was inferred from a type appearing in a 'where' clause, like this: struct G<A, B> {} extension G where B : Hashable, A == Set<B> {} This is because in this case the redundancy was detected by RewriteSystem::addRule() returning false. The simplest fix here is to change InferredGenericSignatureRequest to re-order requirements so that inferred requirements appear last. This way, if any are redundant, we won't diagnose them since it is the inferred requirement that is redundant and not the user-written one. Fixes rdar://problem/92092635.
1 parent 965ba21 commit 307aa46

File tree

4 files changed

+30
-11
lines changed

4 files changed

+30
-11
lines changed

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,15 @@ InferredGenericSignatureRequestRQM::evaluate(
816816
for (const auto &req : addedRequirements)
817817
requirements.push_back({req, SourceLoc(), /*wasInferred=*/true});
818818

819+
// Re-order requirements so that inferred requirements appear last. This
820+
// ensures that if an inferred requirement is redundant with some other
821+
// requirement, it is the inferred requirement that becomes redundant,
822+
// which muffles the redundancy diagnostic.
823+
std::stable_partition(requirements.begin(), requirements.end(),
824+
[](const StructuralRequirement &req) {
825+
return !req.inferred;
826+
});
827+
819828
auto &ctx = moduleForInference->getASTContext();
820829
auto &rewriteCtx = ctx.getRewriteContext();
821830

test/Generics/rdar75656022.swift

Lines changed: 3 additions & 4 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 %s -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify 2>&1 | %FileCheck %s
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on
2+
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures %s -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
33

44
protocol P1 {
55
associatedtype T
@@ -48,8 +48,7 @@ struct OriginalExampleWithWarning<A, B> where A : P2, B : P2, A.T == B.T {
4848
init<C, D, E>(_: C)
4949
where C : P1,
5050
D : P1, // expected-warning {{redundant conformance constraint 'D' : 'P1'}}
51-
C.T : P1, // expected-warning {{redundant conformance constraint 'D' : 'P1'}}
52-
// expected-note@-1 {{conformance constraint 'D' : 'P1' implied here}}
51+
C.T : P1, // expected-warning {{redundant conformance constraint 'C.T' : 'P1'}}
5352
A == S1<C, C.T.T, S2<C.T>>,
5453
C.T == D,
5554
E == D.T { }

test/Generics/rdar77462797.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-inferred-signatures=verify
2-
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-inferred-signatures=verify 2>&1 | %FileCheck %s
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-inferred-signatures=on
2+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
33

44
protocol P {}
55

@@ -21,18 +21,15 @@ struct G<X, Y> where X : Q {
2121

2222
// 'X : Q' is redundant
2323
func foo3() where X : Q, X == S<Y>, Y : P {}
24-
// expected-warning@-1 {{redundant conformance constraint 'X' : 'Q'}}
25-
// expected-note@-2 {{conformance constraint 'X' : 'Q' implied here}}
24+
// expected-warning@-1 {{redundant conformance constraint 'S<Y>' : 'Q'}}
2625
// CHECK: Generic signature: <X, Y where X == S<Y>, Y : P>
2726

2827
// 'T.T : P' is redundant
2928
func foo4<T : Q>(_: T) where X == S<Y>, T.T : P {}
3029
// expected-warning@-1 {{redundant conformance constraint 'T.T' : 'P'}}
31-
// expected-note@-2 {{conformance constraint 'T.T' : 'P' implied here}}
3230
// CHECK: Generic signature: <X, Y, T where X == S<Y>, Y : P, T : Q>
3331
}
3432

3533
func foo<X, Y>(_: X, _: Y) where X : Q, X : S<Y>, Y : P {}
36-
// expected-warning@-1 {{redundant conformance constraint 'X' : 'Q'}}
37-
// expected-note@-2 {{conformance constraint 'X' : 'Q' implied here}}
34+
// expected-warning@-1 {{redundant conformance constraint 'S<Y>' : 'Q'}}
3835
// CHECK: Generic signature: <X, Y where X : S<Y>, Y : P>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol P {}
4+
5+
struct S<T : P> {}
6+
7+
struct G<A, B> {}
8+
9+
extension G where A == S<B>, B : P {}
10+
11+
extension G where B : P, A == S<B> {}
12+
13+
extension G where B : P, A == S<B>, B : P {}
14+
// expected-warning@-1 {{redundant conformance constraint 'B' : 'P'}}

0 commit comments

Comments
 (0)