mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[GSB] Diagnose all same-type-to-concrete conflicts consistently.
This commit is contained in:
@@ -1690,6 +1690,9 @@ NOTE(redundant_conformance_here,none,
|
|||||||
"inferred from type here}0",
|
"inferred from type here}0",
|
||||||
(unsigned, Type, ProtocolDecl *))
|
(unsigned, Type, ProtocolDecl *))
|
||||||
|
|
||||||
|
ERROR(same_type_conflict,none,
|
||||||
|
"%select{generic parameter |protocol |}0%1 cannot be equal to both "
|
||||||
|
"%2 and %3", (unsigned, Type, Type, Type))
|
||||||
WARNING(redundant_same_type_to_concrete,none,
|
WARNING(redundant_same_type_to_concrete,none,
|
||||||
"redundant same-type constraint %0 == %1", (Type, Type))
|
"redundant same-type constraint %0 == %1", (Type, Type))
|
||||||
NOTE(same_type_redundancy_here,none,
|
NOTE(same_type_redundancy_here,none,
|
||||||
|
|||||||
@@ -1728,6 +1728,7 @@ namespace {
|
|||||||
PotentialArchetype *pa;
|
PotentialArchetype *pa;
|
||||||
|
|
||||||
void operator()(Type type1, Type type2) const {
|
void operator()(Type type1, Type type2) const {
|
||||||
|
// FIXME: Shouldn't need this!
|
||||||
if (pa->getParent() && pa->getConcreteTypeDecl() &&
|
if (pa->getParent() && pa->getConcreteTypeDecl() &&
|
||||||
source->getLoc().isInvalid()) {
|
source->getLoc().isInvalid()) {
|
||||||
diags.diagnose(pa->getConcreteTypeDecl()->getLoc(),
|
diags.diagnose(pa->getConcreteTypeDecl()->getLoc(),
|
||||||
@@ -1736,14 +1737,6 @@ namespace {
|
|||||||
type1, type2);
|
type1, type2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source->getLoc().isValid()) {
|
|
||||||
diags.diagnose(source->getLoc(),
|
|
||||||
diag::requires_same_type_conflict,
|
|
||||||
pa->isGenericParam(),
|
|
||||||
pa->getDependentType(/*FIXME: */{ }, true),
|
|
||||||
type1, type2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
@@ -5010,8 +5003,8 @@ void GenericSignatureBuilder::checkConcreteTypeConstraints(
|
|||||||
|
|
||||||
checkConstraintList<Type>(
|
checkConstraintList<Type>(
|
||||||
genericParams, equivClass->concreteTypeConstraints,
|
genericParams, equivClass->concreteTypeConstraints,
|
||||||
[](const ConcreteConstraint &constraint) {
|
[&](const ConcreteConstraint &constraint) {
|
||||||
return true;
|
return constraint.value->isEqual(equivClass->concreteType);
|
||||||
},
|
},
|
||||||
[&](Type concreteType) {
|
[&](Type concreteType) {
|
||||||
// If the concrete type is equivalent, the constraint is redundant.
|
// If the concrete type is equivalent, the constraint is redundant.
|
||||||
@@ -5020,10 +5013,14 @@ void GenericSignatureBuilder::checkConcreteTypeConstraints(
|
|||||||
if (concreteType->isEqual(equivClass->concreteType))
|
if (concreteType->isEqual(equivClass->concreteType))
|
||||||
return ConstraintRelation::Redundant;
|
return ConstraintRelation::Redundant;
|
||||||
|
|
||||||
// Call this unrelated.
|
// If either has a type parameter, call them unrelated.
|
||||||
return ConstraintRelation::Unrelated;
|
if (concreteType->hasTypeParameter() ||
|
||||||
|
equivClass->concreteType->hasTypeParameter())
|
||||||
|
return ConstraintRelation::Unrelated;
|
||||||
|
|
||||||
|
return ConstraintRelation::Conflicting;
|
||||||
},
|
},
|
||||||
None,
|
diag::same_type_conflict,
|
||||||
diag::redundant_same_type_to_concrete,
|
diag::redundant_same_type_to_concrete,
|
||||||
diag::same_type_redundancy_here);
|
diag::same_type_redundancy_here);
|
||||||
|
|
||||||
|
|||||||
@@ -58,14 +58,16 @@ func test3<T: Fooable, U: Fooable>(_ t: T, u: U) -> (X, X)
|
|||||||
func fail1<
|
func fail1<
|
||||||
T: Fooable, U: Fooable
|
T: Fooable, U: Fooable
|
||||||
>(_ t: T, u: U) -> (X, Y)
|
>(_ t: T, u: U) -> (X, Y)
|
||||||
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'}}
|
where T.Foo == X, U.Foo == Y, T.Foo == U.Foo { // expected-error{{'U.Foo' cannot be equal to both 'Y' and 'X'}}
|
||||||
|
// expected-note@-1{{same-type constraint 'T.Foo' == 'X' written here}}
|
||||||
return (t.foo, u.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Y'}}
|
return (t.foo, u.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Y'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fail2<
|
func fail2<
|
||||||
T: Fooable, U: Fooable
|
T: Fooable, U: Fooable
|
||||||
>(_ t: T, u: U) -> (X, Y)
|
>(_ t: T, u: U) -> (X, Y)
|
||||||
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'}}
|
where T.Foo == U.Foo, T.Foo == X, U.Foo == Y { // expected-error{{'U.Foo' cannot be equal to both 'Y' and 'X'}}
|
||||||
|
// expected-note@-1{{same-type constraint 'T.Foo' == 'X' written here}}
|
||||||
return (t.foo, u.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Y'}}
|
return (t.foo, u.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Y'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,20 +96,22 @@ func test7<T: Barrable>(_ t: T) -> (Y, X) where T.Bar == Y, T.Bar.Foo == X {
|
|||||||
|
|
||||||
func fail4<T: Barrable>(_ t: T) -> (Y, Z)
|
func fail4<T: Barrable>(_ t: T) -> (Y, Z)
|
||||||
where
|
where
|
||||||
T.Bar == Y,
|
T.Bar == Y, // expected-note{{same-type constraint 'T.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}}
|
||||||
T.Bar.Foo == Z { // expected-error{{associated type 'T.Bar.Foo' cannot be equal to both 'Y.Foo' (aka 'X') and 'Z'}}
|
T.Bar.Foo == Z { // expected-error{{'T.Bar.Foo' cannot be equal to both 'Z' and 'Y.Foo' (aka 'X')}}
|
||||||
return (t.bar, t.bar.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Z'}}
|
return (t.bar, t.bar.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Z'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fail5<T: Barrable>(_ t: T) -> (Y, Z)
|
func fail5<T: Barrable>(_ t: T) -> (Y, Z)
|
||||||
where
|
where
|
||||||
T.Bar.Foo == Z, // expected-warning{{redundant same-type constraint 'T.Bar.Foo' == 'Z'}}
|
T.Bar.Foo == Z, // expected-note{{same-type constraint 'T.Bar.Foo' == 'Z' written here}}
|
||||||
T.Bar == Y { // expected-error{{associated type 'T.Bar.Foo' cannot be equal to both 'Z' and 'X'}}
|
T.Bar == Y { // expected-error{{'T.Bar.Foo' cannot be equal to both 'Y.Foo' (aka 'X') and 'Z'}}
|
||||||
// expected-note@-1{{same-type constraint 'T.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}}
|
|
||||||
return (t.bar, t.bar.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Z'}}
|
return (t.bar, t.bar.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Z'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
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'}}
|
func test8<T: Fooable>(_ t: T)
|
||||||
|
where T.Foo == X, // expected-note{{same-type constraint 'T.Foo' == 'X' written here}}
|
||||||
|
T.Foo == Y {} // expected-error{{'T.Foo' cannot be equal to both 'Y' and 'X'}}
|
||||||
|
|
||||||
|
|
||||||
func testAssocTypeEquivalence<T: Fooable>(_ fooable: T) -> X.Type
|
func testAssocTypeEquivalence<T: Fooable>(_ fooable: T) -> X.Type
|
||||||
where T.Foo == X {
|
where T.Foo == X {
|
||||||
@@ -246,7 +250,6 @@ func structuralSameTypeRecursive1<T: P2, U>(_: T, _: U)
|
|||||||
where T.Assoc1 == Tuple2<T.Assoc1, U> // expected-error{{same-type constraint 'T.Assoc1' == '(T.Assoc1, U)' is recursive}}
|
where T.Assoc1 == Tuple2<T.Assoc1, U> // expected-error{{same-type constraint 'T.Assoc1' == '(T.Assoc1, U)' is recursive}}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
protocol P3 {
|
protocol P3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,5 +259,25 @@ protocol P4 {
|
|||||||
|
|
||||||
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'}}
|
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'}}
|
||||||
|
|
||||||
|
// Same-type constraint conflict through protocol where clauses.
|
||||||
|
protocol P5 where Foo1 == Foo2 {
|
||||||
|
associatedtype Foo1
|
||||||
|
associatedtype Foo2
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol P6 {
|
||||||
|
associatedtype Bar: P5
|
||||||
|
}
|
||||||
|
|
||||||
|
struct X5a {}
|
||||||
|
|
||||||
|
struct X5b { }
|
||||||
|
|
||||||
|
func test9<T: P6, U: P6>(_ t: T, u: U)
|
||||||
|
where T.Bar.Foo1 == X5a, // expected-note{{same-type constraint 'T.Bar.Foo1' == 'X5a' written here}}
|
||||||
|
U.Bar.Foo2 == X5b, // expected-error{{'U.Bar.Foo2' cannot be equal to both 'X5b' and 'X5a'}}
|
||||||
|
T.Bar == U.Bar {
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Remove -verify-ignore-unknown.
|
// FIXME: Remove -verify-ignore-unknown.
|
||||||
// <unknown>:0: error: unexpected error produced: generic parameter τ_0_0.Bar.Foo cannot be equal to both 'Y.Foo' (aka 'X') and 'Z'
|
// <unknown>:0: error: unexpected error produced: generic parameter τ_0_0.Bar.Foo cannot be equal to both 'Y.Foo' (aka 'X') and 'Z'
|
||||||
|
|||||||
Reference in New Issue
Block a user