Skip to content

Commit 9a6a9a1

Browse files
committed
RequirementMachine: Diagnose redundant concrete conformance requirements
A conformance requirement on a concrete type parameter is redundant if the concrete type conforms to the protocol. The replacement path for the conformance rule is based on a concrete conformance rule introduced by the property map. Since the concrete conformance rule is not associated with a requirement ID, this would normally muffle the redundancy warning, because we don't want to suggest removing a rule that depends on a non-redundant, non-explicit rule. However, concrete conformance rules don't actually appear in the minimal signature, so skip them when computing the set of non-redundant, non-explicit rules to ensure that the original conformance requirement is still diagnosed as redundant.
1 parent 223944b commit 9a6a9a1

File tree

4 files changed

+45
-32
lines changed

4 files changed

+45
-32
lines changed

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,15 @@ void RewriteSystem::computeRedundantRequirementDiagnostics(
661661
if (!isInMinimizationDomain(rule.getLHS().getRootProtocol()))
662662
continue;
663663

664+
// Concrete conformance rules do not map to requirements in the minimized
665+
// signature; we don't consider them to be 'non-explicit non-redundant',
666+
// so that a conformance rule (T.[P] => T) expressed in terms of a concrete
667+
// conformance (T.[concrete: C : P] => T) is still diagnosed as redundant.
668+
if (auto optSymbol = rule.isPropertyRule()) {
669+
if (optSymbol->getKind() == Symbol::Kind::ConcreteConformance)
670+
continue;
671+
}
672+
664673
auto requirementID = rule.getRequirementID();
665674

666675
if (!requirementID.hasValue()) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on
2+
3+
protocol P1 {}
4+
protocol P2 : P1 {}
5+
6+
protocol P3 {
7+
associatedtype A where A == S
8+
}
9+
10+
struct S : P2 {}
11+
12+
func f1<T : P3>(_: T) where T.A : P1 {}
13+
// expected-warning@-1 {{redundant conformance constraint 'T.A' : 'P1'}}
14+
15+
func f2<T : P3>(_: T) where T.A : P2 {}
16+
// expected-warning@-1 {{redundant conformance constraint 'T.A' : 'P2'}}

test/Generics/superclass_constraint.swift

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

55
class A {
@@ -12,13 +12,10 @@ class B : A {
1212

1313
class Other { }
1414

15-
func f1<T : A>(_: T) where T : Other {} // expected-error{{type 'T' cannot be a subclass of both 'Other' and 'A'}}
16-
// expected-note@-1{{constraint conflicts with 'T' : 'A'}}
15+
func f1<T : A>(_: T) where T : Other {} // expected-error{{no type for 'T' can satisfy both 'T : Other' and 'T : A'}}
1716

1817
func f2<T : A>(_: T) where T : B {}
1918
// expected-warning@-1{{redundant superclass constraint 'T' : 'A'}}
20-
// expected-note@-2{{superclass constraint 'T' : 'A' implied here}}
21-
2219

2320
class GA<T> {}
2421
class GB<T> : GA<T> {}
@@ -31,19 +28,16 @@ func f5<T, U : GA<T>>(_: T, _: U) {}
3128
func f6<U : GA<T>, T : P>(_: T, _: U) {}
3229
func f7<U, T>(_: T, _: U) where U : GA<T>, T : P {}
3330

34-
func f8<T : GA<A>>(_: T) where T : GA<B> {} // expected-error{{type 'T' cannot be a subclass of both 'GA<B>' and 'GA<A>'}}
35-
// expected-note@-1{{constraint conflicts with 'T' : 'GA<A>'}}
31+
func f8<T : GA<A>>(_: T) where T : GA<B> {} // expected-error{{no type for 'T' can satisfy both 'T : GA<B>' and 'T : GA<A>'}}
3632

3733
func f9<T : GA<A>>(_: T) where T : GB<A> {}
3834
// expected-warning@-1{{redundant superclass constraint 'T' : 'GA<A>'}}
39-
// expected-note@-2{{superclass constraint 'T' : 'GA<A>' implied here}}
4035

4136
func f10<T : GB<A>>(_: T) where T : GA<A> {}
4237
// expected-warning@-1{{redundant superclass constraint 'T' : 'GA<A>'}}
43-
// expected-note@-2{{superclass constraint 'T' : 'GA<A>' implied here}}
4438

45-
func f11<T : GA<T>>(_: T) { } // expected-error{{superclass constraint 'T' : 'GA<T>' is recursive}}
46-
func f12<T : GA<U>, U : GB<T>>(_: T, _: U) { } // expected-error{{superclass constraint 'U' : 'GB<T>' is recursive}} // expected-error{{superclass constraint 'T' : 'GA<U>' is recursive}}
39+
func f11<T : GA<T>>(_: T) { }
40+
func f12<T : GA<U>, U : GB<T>>(_: T, _: U) { }
4741
func f13<T : U, U : GA<T>>(_: T, _: U) { } // expected-error{{type 'T' constrained to non-protocol, non-class type 'U'}}
4842

4943
// rdar://problem/24730536
@@ -68,16 +62,16 @@ class S : P2 {
6862
// CHECK-LABEL: .superclassConformance1(t:)@
6963
// CHECK-NEXT: Generic signature: <T where T : C>
7064
func superclassConformance1<T>(t: T)
71-
where T : C, // expected-note{{conformance constraint 'T' : 'P3' implied here}}
72-
T : P3 {} // expected-warning{{redundant conformance constraint 'T' : 'P3'}}
65+
where T : C,
66+
T : P3 {} // expected-warning{{redundant conformance constraint 'C' : 'P3'}}
7367

7468

7569

7670
// CHECK-LABEL: .superclassConformance2(t:)@
7771
// CHECK-NEXT: Generic signature: <T where T : C>
7872
func superclassConformance2<T>(t: T)
79-
where T : C, // expected-note{{conformance constraint 'T' : 'P3' implied here}}
80-
T : P3 {} // expected-warning{{redundant conformance constraint 'T' : 'P3'}}
73+
where T : C,
74+
T : P3 {} // expected-warning{{redundant conformance constraint 'C' : 'P3'}}
8175

8276
protocol P4 { }
8377

@@ -87,32 +81,28 @@ class C2 : C, P4 { }
8781
// CHECK-NEXT: Generic signature: <T where T : C2>
8882
func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {}
8983
// expected-warning@-1{{redundant superclass constraint 'T' : 'C'}}
90-
// expected-note@-2{{superclass constraint 'T' : 'C' implied here}}
91-
// expected-warning@-3{{redundant conformance constraint 'T' : 'P4'}}
92-
// expected-note@-4{{conformance constraint 'T' : 'P4' implied here}}
84+
// expected-warning@-2{{redundant conformance constraint 'T' : 'P4'}}
9385

9486
protocol P5: A { }
9587

96-
protocol P6: A, Other { } // expected-error {{type 'Self' cannot be a subclass of both 'Other' and 'A'}}
88+
protocol P6: A, Other { } // expected-error {{no type for 'Self' can satisfy both 'Self : Other' and 'Self : A'}}
9789
// expected-error@-1{{multiple inheritance from classes 'A' and 'Other'}}
98-
// expected-note@-2 {{constraint conflicts with 'Self' : 'A'}}
9990

10091
func takeA(_: A) { }
10192
func takeP5<T: P5>(_ t: T) {
10293
takeA(t) // okay
10394
}
10495

10596
protocol P7 {
106-
associatedtype Assoc: A, Other
107-
// expected-note@-1{{constraint conflicts with 'Self.Assoc' : 'A'}}
108-
// expected-error@-2{{'Self.Assoc' cannot be a subclass of both 'Other' and 'A'}}
97+
// expected-error@-1{{no type for 'Self.Assoc' can satisfy both 'Self.Assoc : Other' and 'Self.Assoc : A'}}
98+
associatedtype Assoc: A, Other
10999
}
110100

111101
// CHECK-LABEL: .superclassConformance4@
112102
// CHECK-NEXT: Generic signature: <T, U where T : P3, U : P3, T.[P3]T : C, T.[P3]T == U.[P3]T>
113103
func superclassConformance4<T: P3, U: P3>(_: T, _: U)
114-
where T.T: C, // expected-note{{superclass constraint 'U.T' : 'C' implied here}}
115-
U.T: C, // expected-warning{{redundant superclass constraint 'U.T' : 'C'}}
104+
where T.T: C, // expected-warning{{redundant superclass constraint 'T.T' : 'C'}}
105+
U.T: C,
116106
T.T == U.T { }
117107

118108
// Lookup of superclass associated types from inheritance clause
@@ -181,8 +171,7 @@ protocol Rump : Tail {
181171
class Horse<T>: Rump { }
182172

183173
func hasRedundantConformanceConstraint<X : Horse<T>, T>(_: X) where X : Rump {}
184-
// expected-warning@-1 {{redundant conformance constraint 'X' : 'Rump'}}
185-
// expected-note@-2 {{conformance constraint 'X' : 'Rump' implied here}}
174+
// expected-warning@-1 {{redundant conformance constraint 'Horse<T>' : 'Rump'}}
186175

187176
// SR-5862
188177
protocol X {

validation-test/compiler_crashers_2_fixed/0145-sr7097.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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
3-
// RUN: %target-swift-frontend -primary-file %s -emit-ir -o - -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-inferred-signatures=on
2+
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures %s -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
3+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -o - -requirement-machine-inferred-signatures=on
44

55
protocol P1 { }
66

@@ -13,7 +13,6 @@ protocol P2 {
1313
protocol P3 : P2 { }
1414

1515
struct S0<M: P3> where M.Assoc: P1 { } // expected-warning{{redundant conformance constraint 'M.Assoc' : 'P1'}}
16-
// expected-note@-1{{conformance constraint 'M.Assoc' : 'P1' implied here}}
1716

1817
struct ConformsToP1: P1 { }
1918

0 commit comments

Comments
 (0)