Skip to content

Commit 0549822

Browse files
authored
Merge pull request #7228 from DougGregor/more-constraint-minimization
2 parents 2fd07f2 + ea90fa6 commit 0549822

File tree

2 files changed

+78
-21
lines changed

2 files changed

+78
-21
lines changed

lib/AST/ArchetypeBuilder.cpp

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,8 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
14131413

14141414
// Make sure the concrete type fulfills the superclass requirement
14151415
// of the archetype.
1416+
RequirementSource redundantSource(RequirementSource::Redundant,
1417+
Source.getLoc());
14161418
if (T->Superclass) {
14171419
if (!T->Superclass->isExactSuperclassOf(Concrete, getLazyResolver())) {
14181420
Diags.diagnose(Source.getLoc(), diag::type_does_not_inherit,
@@ -1422,6 +1424,10 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
14221424
.highlight(T->SuperclassSource->getLoc());
14231425
return true;
14241426
}
1427+
1428+
// The superclass requirement is made redundant by the concrete type
1429+
// assignment.
1430+
updateRequirementSource(*T->SuperclassSource, redundantSource);
14251431
}
14261432

14271433
// Recursively resolve the associated types to their concrete types.
@@ -1432,7 +1438,7 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
14321438
if (auto *concreteArchetype = Concrete->getAs<ArchetypeType>()) {
14331439
Type witnessType = concreteArchetype->getNestedType(nested.first);
14341440
addSameTypeRequirementToConcrete(nested.second.front(), witnessType,
1435-
Source);
1441+
redundantSource);
14361442
} else if (assocType) {
14371443
assert(conformances.count(assocType->getProtocol()) > 0
14381444
&& "missing conformance?");
@@ -1449,11 +1455,11 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
14491455
if (auto witnessPA = resolveArchetype(witnessType)) {
14501456
addSameTypeRequirementBetweenArchetypes(nested.second.front(),
14511457
witnessPA,
1452-
Source);
1458+
redundantSource);
14531459
} else {
14541460
addSameTypeRequirementToConcrete(nested.second.front(),
14551461
witnessType,
1456-
Source);
1462+
redundantSource);
14571463
}
14581464
}
14591465
}
@@ -2173,17 +2179,39 @@ void ArchetypeBuilder::enumerateRequirements(llvm::function_ref<
21732179
RequirementSource source)> f) {
21742180
// Create anchors for all of the potential archetypes.
21752181
// FIXME: This is because we might be missing some from the equivalence
2176-
// classes.
2182+
// classes. It is an egregious hack.
21772183
visitPotentialArchetypes([&](PotentialArchetype *archetype) {
2178-
archetype->getArchetypeAnchor(*this);
2184+
(void)archetype->getArchetypeAnchor(*this);
21792185
});
21802186

2181-
// Collect all archetypes, and sort them.
2187+
// Collect all archetypes.
21822188
SmallVector<PotentialArchetype *, 8> archetypes;
21832189
visitPotentialArchetypes([&](PotentialArchetype *archetype) {
21842190
archetypes.push_back(archetype);
21852191
});
21862192

2193+
// Remove any invalid potential archetypes or archetypes whose parents are
2194+
// concrete; they have no requirements.
2195+
archetypes.erase(
2196+
std::remove_if(archetypes.begin(), archetypes.end(),
2197+
[&](PotentialArchetype *archetype) -> bool {
2198+
// Invalid archetypes are never representatives in well-formed or
2199+
// corrected signature, so we don't need to visit them.
2200+
if (archetype->isInvalid())
2201+
return true;
2202+
2203+
// If there is a concrete type above us, there are no requirements to
2204+
// emit.
2205+
if (archetype->getParent() &&
2206+
hasConcreteTypeInPath(archetype->getParent()))
2207+
return true;
2208+
2209+
// Keep it.
2210+
return false;
2211+
}),
2212+
archetypes.end());
2213+
2214+
// Sort the archetypes in canonical order.
21872215
llvm::array_pod_sort(archetypes.begin(), archetypes.end(),
21882216
compareDependentTypes);
21892217

@@ -2203,32 +2231,27 @@ void ArchetypeBuilder::enumerateRequirements(llvm::function_ref<
22032231
};
22042232

22052233
for (auto *archetype : archetypes) {
2206-
// Invalid archetypes are never representatives in well-formed or corrected
2207-
// signature, so we don't need to visit them.
2208-
if (archetype->isInvalid())
2209-
continue;
2210-
2211-
// If this type is equivalent to a concrete type, emit the same-type
2212-
// constraint.
2213-
auto rep = archetype->getRepresentative();
2214-
if (auto concreteType = rep->getConcreteType()) {
2215-
f(RequirementKind::SameType, archetype, concreteType,
2216-
rep->getConcreteTypeSource());
2217-
continue;
2218-
}
2219-
22202234
// Check whether this archetype is one of the anchors within its
2221-
// connected component. If so, we may need to emit an archetype anchor.
2235+
// connected component. If so, we may need to emit a same-type constraint.
22222236
//
22232237
// FIXME: O(n) in the number of implied connected components within the
22242238
// equivalence class. The equivalence class should be small, but...
2239+
auto rep = archetype->getRepresentative();
22252240
auto componentAnchors = getSameTypeComponentAnchors(rep);
22262241
auto knownAnchor = std::find(componentAnchors.begin(),
22272242
componentAnchors.end(),
22282243
archetype);
22292244
std::function<void()> deferredSameTypeRequirement;
22302245

22312246
if (knownAnchor != componentAnchors.end()) {
2247+
// If this equivalance class is bound to a concrete type, equate the
2248+
// anchor with a concrete type.
2249+
if (auto concreteType = rep->getConcreteType()) {
2250+
f(RequirementKind::SameType, archetype, concreteType,
2251+
rep->getConcreteTypeSource());
2252+
continue;
2253+
}
2254+
22322255
// If we're at the last anchor in the component, do nothing;
22332256
auto nextAnchor = knownAnchor;
22342257
++nextAnchor;

test/Generics/requirement_inference.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,37 @@ extension P7 where AssocP6.Element : P6,
153153
AssocP6.Element == AssocP7.AssocP6.Element {
154154
func nestedSameType1() { }
155155
}
156+
157+
protocol P8 {
158+
associatedtype A
159+
associatedtype B
160+
}
161+
162+
protocol P9 : P8 {
163+
associatedtype A
164+
associatedtype B
165+
}
166+
167+
protocol P10 {
168+
associatedtype A
169+
associatedtype C
170+
}
171+
172+
// CHECK-LABEL: sameTypeConcrete1@
173+
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P10, τ_0_0 : P9, τ_0_0.A == X3, τ_0_0.B == Int, τ_0_0.C == Int>
174+
func sameTypeConcrete1<T : P9 & P10>(_: T) where T.A == X3, T.C == T.B, T.C == Int { }
175+
176+
// CHECK-LABEL: sameTypeConcrete2@
177+
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P10, τ_0_0 : P9, τ_0_0.B == X3, τ_0_0.C == X3>
178+
func sameTypeConcrete2<T : P9 & P10>(_: T) where T.B : X3, T.C == T.B, T.C == X3 { }
179+
180+
// Note: a standard-library-based stress test to make sure we don't inject
181+
// any additional requirements.
182+
// CHECK-LABEL: RangeReplaceableCollection.f()@
183+
// CHECK: <τ_0_0 where τ_0_0 : MutableCollection, τ_0_0 : RangeReplaceableCollection, τ_0_0.SubSequence == MutableRangeReplaceableSlice<τ_0_0>>
184+
extension RangeReplaceableCollection where
185+
Self: MutableCollection,
186+
Self.SubSequence == MutableRangeReplaceableSlice<Self>
187+
{
188+
func f() { }
189+
}

0 commit comments

Comments
 (0)