Skip to content

Commit 05f1b24

Browse files
committed
[Archetype builder] Never use the representative as the archetype anchor.
The "representative" potential archetype chosen by the archetype builder is essentially chosen at random, because this is a union-find data structure. Therefore, it should never be used as the "archetype anchor", which is the canonical representative of an equivalence class that affects both semantics and ABI. Decouple the computation of the archetype anchor from the representative, and verify that the chosen archetype anchor no worse than all other choices.
1 parent 1115c25 commit 05f1b24

File tree

2 files changed

+17
-16
lines changed

2 files changed

+17
-16
lines changed

lib/AST/ArchetypeBuilder.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -374,13 +374,22 @@ bool ArchetypeBuilder::PotentialArchetype::isBetterArchetypeAnchor(
374374
auto ArchetypeBuilder::PotentialArchetype::getArchetypeAnchor()
375375
-> PotentialArchetype * {
376376

377-
// Default to the representative, unless we find something better.
378-
PotentialArchetype *best = getRepresentative();
379-
for (auto pa : best->getEquivalenceClass()) {
377+
// Find the best archetype within this equivalence class.
378+
PotentialArchetype *rep = getRepresentative();
379+
auto best = rep;
380+
for (auto pa : rep->getEquivalenceClass()) {
380381
if (pa->isBetterArchetypeAnchor(best))
381382
best = pa;
382383
}
383384

385+
#ifndef NDEBUG
386+
// Make sure that we did, in fact, get one that is better than all others.
387+
for (auto pa : rep->getEquivalenceClass()) {
388+
assert(!pa->isBetterArchetypeAnchor(best) &&
389+
"archetype anchor isn't a total order");
390+
}
391+
#endif
392+
384393
return best;
385394
}
386395

@@ -1049,18 +1058,10 @@ static int compareDependentTypes(ArchetypeBuilder::PotentialArchetype * const* p
10491058
if (int compareProtocols
10501059
= ProtocolType::compareProtocols(&protoa, &protob))
10511060
return compareProtocols;
1052-
1053-
// - if one is the representative, put it first.
1054-
if ((a->getRepresentative() == a) !=
1055-
(b->getRepresentative() == b))
1056-
return a->getRepresentative() ? -1 : 1;
1057-
1058-
// FIXME: Would be nice if this was a total order.
1059-
return 0;
1061+
} else {
1062+
// A resolved archetype is always ordered before an unresolved one.
1063+
return -1;
10601064
}
1061-
1062-
// A resolved archetype is always ordered before an unresolved one.
1063-
return -1;
10641065
}
10651066

10661067
// A resolved archetype is always ordered before an unresolved one.

test/Generics/associated_type_typo.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
3939
// CHECK-GENERIC-LABEL: .typoAssoc4@
4040
// CHECK-GENERIC-NEXT: Requirements:
4141
// CHECK-GENERIC-NEXT: T : P2 [explicit
42-
// CHECK-GENERIC-NEXT: T[.P2].AssocP2 == T[.P2].AssocP2 [redundant]
4342
// CHECK-GENERIC-NEXT: T[.P2].AssocP2 : P1 [protocol
44-
// CHECK-GENERIC-NEXT: T[.P2].AssocP2[.P1].Assoc == T[.P2].AssocP2[.P1].Assoc [redundant
43+
// CHECK-GENERIC-NEXT: T[.P2].AssocP2 == T[.P2].AssocP2 [redundant]
4544
// CHECK-GENERIC-NEXT: T[.P2].AssocP2[.P1].Assoc : P3 [explicit
45+
// CHECK-GENERIC-NEXT: T[.P2].AssocP2[.P1].Assoc == T[.P2].AssocP2[.P1].Assoc [redundant
4646
// CHECK-GENERIC-NEXT: Generic signature
4747

4848
// <rdar://problem/19620340>

0 commit comments

Comments
 (0)