Skip to content

Commit b51529f

Browse files
committed
[GSB] Diagnose all same-type-to-concrete conflicts consistently.
1 parent bf730ff commit b51529f

File tree

3 files changed

+45
-22
lines changed

3 files changed

+45
-22
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,6 +1690,9 @@ NOTE(redundant_conformance_here,none,
16901690
"inferred from type here}0",
16911691
(unsigned, Type, ProtocolDecl *))
16921692

1693+
ERROR(same_type_conflict,none,
1694+
"%select{generic parameter |protocol |}0%1 cannot be equal to both "
1695+
"%2 and %3", (unsigned, Type, Type, Type))
16931696
WARNING(redundant_same_type_to_concrete,none,
16941697
"redundant same-type constraint %0 == %1", (Type, Type))
16951698
NOTE(same_type_redundancy_here,none,

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,6 +1728,7 @@ namespace {
17281728
PotentialArchetype *pa;
17291729

17301730
void operator()(Type type1, Type type2) const {
1731+
// FIXME: Shouldn't need this!
17311732
if (pa->getParent() && pa->getConcreteTypeDecl() &&
17321733
source->getLoc().isInvalid()) {
17331734
diags.diagnose(pa->getConcreteTypeDecl()->getLoc(),
@@ -1736,14 +1737,6 @@ namespace {
17361737
type1, type2);
17371738
return;
17381739
}
1739-
1740-
if (source->getLoc().isValid()) {
1741-
diags.diagnose(source->getLoc(),
1742-
diag::requires_same_type_conflict,
1743-
pa->isGenericParam(),
1744-
pa->getDependentType(/*FIXME: */{ }, true),
1745-
type1, type2);
1746-
}
17471740
}
17481741
};
17491742
} // end anonymous namespace
@@ -5010,8 +5003,8 @@ void GenericSignatureBuilder::checkConcreteTypeConstraints(
50105003

50115004
checkConstraintList<Type>(
50125005
genericParams, equivClass->concreteTypeConstraints,
5013-
[](const ConcreteConstraint &constraint) {
5014-
return true;
5006+
[&](const ConcreteConstraint &constraint) {
5007+
return constraint.value->isEqual(equivClass->concreteType);
50155008
},
50165009
[&](Type concreteType) {
50175010
// If the concrete type is equivalent, the constraint is redundant.
@@ -5020,10 +5013,14 @@ void GenericSignatureBuilder::checkConcreteTypeConstraints(
50205013
if (concreteType->isEqual(equivClass->concreteType))
50215014
return ConstraintRelation::Redundant;
50225015

5023-
// Call this unrelated.
5024-
return ConstraintRelation::Unrelated;
5016+
// If either has a type parameter, call them unrelated.
5017+
if (concreteType->hasTypeParameter() ||
5018+
equivClass->concreteType->hasTypeParameter())
5019+
return ConstraintRelation::Unrelated;
5020+
5021+
return ConstraintRelation::Conflicting;
50255022
},
5026-
None,
5023+
diag::same_type_conflict,
50275024
diag::redundant_same_type_to_concrete,
50285025
diag::same_type_redundancy_here);
50295026

test/Constraints/same_types.swift

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,16 @@ func test3<T: Fooable, U: Fooable>(_ t: T, u: U) -> (X, X)
5858
func fail1<
5959
T: Fooable, U: Fooable
6060
>(_ t: T, u: U) -> (X, Y)
61-
where T.Foo == X, U.Foo == Y, T.Foo == U.Foo { // expected-error{{associated type 'T.Foo' cannot be equal to both 'X' and 'Y'}}
61+
where T.Foo == X, U.Foo == Y, T.Foo == U.Foo { // expected-error{{'U.Foo' cannot be equal to both 'Y' and 'X'}}
62+
// expected-note@-1{{same-type constraint 'T.Foo' == 'X' written here}}
6263
return (t.foo, u.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Y'}}
6364
}
6465

6566
func fail2<
6667
T: Fooable, U: Fooable
6768
>(_ t: T, u: U) -> (X, Y)
68-
where T.Foo == U.Foo, T.Foo == X, U.Foo == Y { // expected-error{{associated type 'U.Foo' cannot be equal to both 'X' and 'Y'}}
69+
where T.Foo == U.Foo, T.Foo == X, U.Foo == Y { // expected-error{{'U.Foo' cannot be equal to both 'Y' and 'X'}}
70+
// expected-note@-1{{same-type constraint 'T.Foo' == 'X' written here}}
6971
return (t.foo, u.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Y'}}
7072
}
7173

@@ -94,20 +96,22 @@ func test7<T: Barrable>(_ t: T) -> (Y, X) where T.Bar == Y, T.Bar.Foo == X {
9496

9597
func fail4<T: Barrable>(_ t: T) -> (Y, Z)
9698
where
97-
T.Bar == Y,
98-
T.Bar.Foo == Z { // expected-error{{associated type 'T.Bar.Foo' cannot be equal to both 'Y.Foo' (aka 'X') and 'Z'}}
99+
T.Bar == Y, // expected-note{{same-type constraint 'T.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}}
100+
T.Bar.Foo == Z { // expected-error{{'T.Bar.Foo' cannot be equal to both 'Z' and 'Y.Foo' (aka 'X')}}
99101
return (t.bar, t.bar.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Z'}}
100102
}
101103

102104
func fail5<T: Barrable>(_ t: T) -> (Y, Z)
103105
where
104-
T.Bar.Foo == Z, // expected-warning{{redundant same-type constraint 'T.Bar.Foo' == 'Z'}}
105-
T.Bar == Y { // expected-error{{associated type 'T.Bar.Foo' cannot be equal to both 'Z' and 'X'}}
106-
// expected-note@-1{{same-type constraint 'T.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}}
106+
T.Bar.Foo == Z, // expected-note{{same-type constraint 'T.Bar.Foo' == 'Z' written here}}
107+
T.Bar == Y { // expected-error{{'T.Bar.Foo' cannot be equal to both 'Y.Foo' (aka 'X') and 'Z'}}
107108
return (t.bar, t.bar.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Z'}}
108109
}
109110

110-
func test8<T: Fooable>(_ t: T) where T.Foo == X, T.Foo == Y {} // expected-error{{associated type 'T.Foo' cannot be equal to both 'X' and 'Y'}}
111+
func test8<T: Fooable>(_ t: T)
112+
where T.Foo == X, // expected-note{{same-type constraint 'T.Foo' == 'X' written here}}
113+
T.Foo == Y {} // expected-error{{'T.Foo' cannot be equal to both 'Y' and 'X'}}
114+
111115

112116
func testAssocTypeEquivalence<T: Fooable>(_ fooable: T) -> X.Type
113117
where T.Foo == X {
@@ -246,7 +250,6 @@ func structuralSameTypeRecursive1<T: P2, U>(_: T, _: U)
246250
where T.Assoc1 == Tuple2<T.Assoc1, U> // expected-error{{same-type constraint 'T.Assoc1' == '(T.Assoc1, U)' is recursive}}
247251
{ }
248252

249-
250253
protocol P3 {
251254
}
252255

@@ -256,5 +259,25 @@ protocol P4 {
256259

257260
func test9<T>(_: T) where T.A == X, T: P4, T.A: P3 { } // expected-error{{same-type constraint type 'X' does not conform to required protocol 'P3'}}
258261

262+
// Same-type constraint conflict through protocol where clauses.
263+
protocol P5 where Foo1 == Foo2 {
264+
associatedtype Foo1
265+
associatedtype Foo2
266+
}
267+
268+
protocol P6 {
269+
associatedtype Bar: P5
270+
}
271+
272+
struct X5a {}
273+
274+
struct X5b { }
275+
276+
func test9<T: P6, U: P6>(_ t: T, u: U)
277+
where T.Bar.Foo1 == X5a, // expected-note{{same-type constraint 'T.Bar.Foo1' == 'X5a' written here}}
278+
U.Bar.Foo2 == X5b, // expected-error{{'U.Bar.Foo2' cannot be equal to both 'X5b' and 'X5a'}}
279+
T.Bar == U.Bar {
280+
}
281+
259282
// FIXME: Remove -verify-ignore-unknown.
260283
// <unknown>:0: error: unexpected error produced: generic parameter τ_0_0.Bar.Foo cannot be equal to both 'Y.Foo' (aka 'X') and 'Z'

0 commit comments

Comments
 (0)