Skip to content

Commit c443739

Browse files
committed
[GSB] Centralize reporting of same-type conflicts.
This eliminates a bunch of code repetition and handles "typealias" conflict diagnostics more uniformly.
1 parent 3c9f7a4 commit c443739

File tree

2 files changed

+45
-56
lines changed

2 files changed

+45
-56
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 42 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,35 @@ PotentialArchetype *PotentialArchetype::getArchetypeAnchor(
11561156
return anchor;
11571157
}
11581158

1159+
namespace {
1160+
/// Function object to diagnose a conflict in same-type constraints for a
1161+
/// given potential archetype.
1162+
struct DiagnoseSameTypeConflict {
1163+
DiagnosticEngine &diags;
1164+
const RequirementSource *source;
1165+
PotentialArchetype *pa;
1166+
1167+
void operator()(Type type1, Type type2) const {
1168+
if (pa->getParent() && pa->getTypeAliasDecl() &&
1169+
source->getLoc().isInvalid()) {
1170+
diags.diagnose(pa->getTypeAliasDecl()->getLoc(),
1171+
diag::protocol_typealias_conflict,
1172+
pa->getTypeAliasDecl()->getName(),
1173+
type1, type2);
1174+
return;
1175+
}
1176+
1177+
if (source->getLoc().isValid()) {
1178+
diags.diagnose(source->getLoc(),
1179+
diag::requires_same_type_conflict,
1180+
pa->isGenericParam(),
1181+
pa->getDependentType(/*FIXME: */{ }, true),
1182+
type1, type2);
1183+
}
1184+
}
1185+
};
1186+
}
1187+
11591188
// Give a nested type the appropriately resolved concrete type, based off a
11601189
// parent PA that has a concrete type.
11611190
static void concretizeNestedTypeFromConcreteParent(
@@ -1190,14 +1219,10 @@ static void concretizeNestedTypeFromConcreteParent(
11901219
}
11911220

11921221
builder.addSameTypeRequirement(nestedPA, witnessType, source,
1193-
[&](Type type1, Type type2) {
1194-
builder.getASTContext().Diags.diagnose(
1195-
source->getLoc(),
1196-
diag::requires_same_type_conflict,
1197-
nestedPA->isGenericParam(),
1198-
nestedPA->getDependentType(/*FIXME: */{ }, true),
1199-
type1, type2);
1200-
});
1222+
DiagnoseSameTypeConflict{
1223+
builder.getASTContext().Diags,
1224+
source, nestedPA
1225+
});
12011226
}
12021227

12031228
PotentialArchetype *PotentialArchetype::getNestedType(
@@ -1439,24 +1464,6 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
14391464
if (shouldUpdatePA) {
14401465
// For typealiases, introduce a same-type requirement to the aliased type.
14411466
if (typealias) {
1442-
auto diagnoseMismatch = [&](Type first, Type second) {
1443-
if (auto NAT = dyn_cast<NameAliasType>(first.getPointer())) {
1444-
if (NAT->getDecl() == typealias) {
1445-
// If we have typealias T = Foo and Foo is completely concrete
1446-
// (e.g. Array<Int?>), then the subst will leave the NameAliasType
1447-
// intact. However, this means, if there's a
1448-
// concrete-type-mismatch at the top level, the default error
1449-
// message will be "ProtocolName.T (aka Foo)", but the "T" bit is
1450-
// already in the error message so it's better to print only
1451-
// "Foo".
1452-
first = NAT->getSinglyDesugaredType();
1453-
}
1454-
}
1455-
builder.Diags.diagnose(typealias->getLoc(),
1456-
diag::protocol_typealias_conflict,
1457-
typealias->getName(), first, second);
1458-
};
1459-
14601467
// FIXME (recursive decl validation): if the alias doesn't have an
14611468
// interface type when getNestedType is called while building a
14621469
// protocol's generic signature (i.e. during validation), then it'll
@@ -1481,8 +1488,7 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
14811488
builder.addSameTypeRequirement(
14821489
ResolvedType::forNewTypeAlias(resultPA),
14831490
builder.resolve(type),
1484-
RequirementSource::forNestedTypeNameMatch(resultPA),
1485-
diagnoseMismatch);
1491+
RequirementSource::forNestedTypeNameMatch(resultPA));
14861492
}
14871493
}
14881494

@@ -2229,14 +2235,9 @@ bool GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
22292235

22302236
// FIXME: This seems early.
22312237
if (concrete1 && concrete2) {
2232-
bool mismatch = addSameTypeRequirement(
2233-
concrete1, concrete2, Source, [&](Type type1, Type type2) {
2234-
Diags.diagnose(Source->getLoc(),
2235-
diag::requires_same_type_conflict,
2236-
T1->isGenericParam(),
2237-
T1->getDependentType(/*FIXME: */{ }, true), type1,
2238-
type2);
2239-
});
2238+
bool mismatch = addSameTypeRequirement(concrete1, concrete2, Source,
2239+
DiagnoseSameTypeConflict{
2240+
Diags, Source, T1});
22402241

22412242
if (mismatch) return true;
22422243
}
@@ -2315,13 +2316,7 @@ bool GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
23152316
if (addSameTypeRequirement(
23162317
T1Nested, T2Nested.second.front(),
23172318
RequirementSource::forNestedTypeNameMatch(T1Nested),
2318-
[&](Type type1, Type type2) {
2319-
Diags.diagnose(Source->getLoc(),
2320-
diag::requires_same_type_conflict,
2321-
T1Nested->isGenericParam(),
2322-
T1Nested->getDependentType(/*FIXME: */{ }, true),
2323-
type1, type2);
2324-
}))
2319+
DiagnoseSameTypeConflict{Diags, Source, T1Nested}))
23252320
return true;
23262321
}
23272322
}
@@ -2342,16 +2337,10 @@ bool GenericSignatureBuilder::addSameTypeRequirementToConcrete(
23422337

23432338
// If we've already been bound to a type, match that type.
23442339
if (equivClass->concreteType) {
2345-
bool mismatch = addSameTypeRequirement(
2346-
equivClass->concreteType, Concrete, Source,
2347-
[&](Type type1, Type type2) {
2348-
Diags.diagnose(Source->getLoc(),
2349-
diag::requires_same_type_conflict,
2350-
T->isGenericParam(),
2351-
T->getDependentType(/*FIXME: */{ }, true), type1,
2352-
type2);
2353-
2354-
});
2340+
bool mismatch = addSameTypeRequirement(equivClass->concreteType, Concrete,
2341+
Source,
2342+
DiagnoseSameTypeConflict{
2343+
Diags, Source, T});
23552344

23562345
if (mismatch) return true;
23572346

test/Generics/protocol_type_aliases.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ protocol Q2 {
3636
// CHECK-NEXT: Requirements:
3737
// CHECK-NEXT: τ_0_0 : Q2 [τ_0_0: Explicit @ 42:59]
3838
// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 42:59 -> Protocol requirement (via Self.B in Q2)]
39-
// CHECK-NEXT: τ_0_0[.Q2].C == S<T.B.A> [τ_0_0[.Q2].C: Explicit @ 42:69]
39+
// CHECK-NEXT: τ_0_0[.Q2].C == S<T.B.A> [τ_0_0[.Q2].C: Explicit]
4040
// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Nested type match]
4141
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == S<τ_0_0.B.A>>
4242
func requirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, T.C == T.B.X {}
@@ -53,14 +53,14 @@ func concreteRequirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, S<T.C> =
5353

5454
// Incompatible concrete typealias types are flagged as such
5555
protocol P3 {
56-
typealias T = Int // expected-error{{typealias 'T' requires types 'Int' and 'Float' to be the same}}
56+
typealias T = Int // expected-error{{typealias 'T' requires types 'Q3.T' (aka 'Float') and 'Int' to be the same}}
5757
}
5858
protocol Q3: P3 {
5959
typealias T = Float
6060
}
6161

6262
protocol P3_1 {
63-
typealias T = Float // expected-error{{typealias 'T' requires types 'Float' and 'Int' to be the same}}
63+
typealias T = Float // expected-error{{typealias 'T' requires types 'P3.T' (aka 'Int') and 'Float' to be the same}}
6464
}
6565
protocol Q3_1: P3, P3_1 {}
6666

0 commit comments

Comments
 (0)