Skip to content

Commit 652edc9

Browse files
authored
Merge pull request #12607 from DougGregor/gsb-less-potential-archetype-realization
2 parents 30b6fdc + d2f0df4 commit 652edc9

File tree

2 files changed

+98
-116
lines changed

2 files changed

+98
-116
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -452,8 +452,8 @@ class GenericSignatureBuilder {
452452

453453
/// \brief Add a new conformance requirement specifying that the given
454454
/// potential archetype is bound to a concrete type.
455-
ConstraintResult addSameTypeRequirementToConcrete(PotentialArchetype *T,
456-
Type Concrete,
455+
ConstraintResult addSameTypeRequirementToConcrete(ResolvedType type,
456+
Type concrete,
457457
const RequirementSource *Source);
458458

459459
/// \brief Add a new same-type requirement specifying that the given two
@@ -1458,11 +1458,6 @@ struct GenericSignatureBuilder::Constraint {
14581458
Type getSubjectDependentType(
14591459
ArrayRef<GenericTypeParamType *> genericParams) const;
14601460

1461-
/// Realizes and retrieves the potential archetype describing the
1462-
/// subject of the constraint.
1463-
PotentialArchetype *realizeSubjectPotentialArchetype(
1464-
GenericSignatureBuilder &builder) const;
1465-
14661461
/// Determine whether the subject is equivalence to the given potential
14671462
/// archetype.
14681463
bool isSubjectEqualTo(const PotentialArchetype *pa) const;

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 96 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,26 +1660,6 @@ Type Constraint<T>::getSubjectDependentType(
16601660
return subject.get<PotentialArchetype *>()->getDependentType(genericParams);
16611661
}
16621662

1663-
template<typename T>
1664-
PotentialArchetype *Constraint<T>::realizeSubjectPotentialArchetype(
1665-
GenericSignatureBuilder &builder) const {
1666-
if (auto pa = subject.dyn_cast<PotentialArchetype *>())
1667-
return pa;
1668-
1669-
auto type = subject.get<Type>();
1670-
auto pa =
1671-
builder.maybeResolveEquivalenceClass(type,
1672-
ArchetypeResolutionKind::WellFormed,
1673-
/*wantExactPotentialArchetype=*/true)
1674-
.realizePotentialArchetype(builder);
1675-
assert(pa && "Invalid dependent type");
1676-
1677-
// Cache the result, so we don't need to realize the potential archetype
1678-
// again.
1679-
subject = pa;
1680-
return pa;
1681-
}
1682-
16831663
template<typename T>
16841664
bool Constraint<T>::isSubjectEqualTo(const PotentialArchetype *pa) const {
16851665
if (auto subjectPA = subject.dyn_cast<PotentialArchetype *>())
@@ -4127,39 +4107,38 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
41274107
}
41284108

41294109
ConstraintResult GenericSignatureBuilder::addSameTypeRequirementToConcrete(
4130-
PotentialArchetype *T,
4131-
Type Concrete,
4132-
const RequirementSource *Source) {
4133-
auto rep = T->getRepresentative();
4134-
auto equivClass = rep->getOrCreateEquivalenceClass(*this);
4110+
ResolvedType type,
4111+
Type concrete,
4112+
const RequirementSource *source) {
4113+
auto equivClass = type.getEquivalenceClass(*this);
41354114

41364115
// Record the concrete type and its source.
41374116
equivClass->concreteTypeConstraints.push_back(
4138-
ConcreteConstraint{T, Concrete, Source});
4117+
ConcreteConstraint{type.getUnresolvedType(), concrete, source});
41394118
equivClass->modified(*this);
41404119
++NumConcreteTypeConstraints;
41414120

41424121
// If we've already been bound to a type, match that type.
41434122
if (equivClass->concreteType) {
4144-
return addSameTypeRequirement(equivClass->concreteType, Concrete, Source,
4123+
return addSameTypeRequirement(equivClass->concreteType, concrete, source,
41454124
UnresolvedHandlingKind::GenerateConstraints,
41464125
SameTypeConflictCheckedLater());
41474126

41484127
}
41494128

41504129
// Record the requirement.
4151-
equivClass->concreteType = Concrete;
4130+
equivClass->concreteType = concrete;
41524131

41534132
// Make sure the concrete type fulfills the conformance requirements of
41544133
// this equivalence class.
41554134
for (const auto &conforms : equivClass->conformsTo) {
4156-
if (!resolveConcreteConformance(rep, conforms.first))
4135+
if (!resolveConcreteConformance(type, conforms.first))
41574136
return ConstraintResult::Conflicting;
41584137
}
41594138

41604139
// Eagerly resolve any existing nested types to their concrete forms (others
41614140
// will be "concretized" as they are constructed, in getNestedType).
4162-
for (auto equivT : rep->getEquivalenceClassMembers()) {
4141+
for (auto equivT : equivClass->members) {
41634142
for (auto nested : equivT->getNestedTypes()) {
41644143
concretizeNestedTypeFromConcreteParent(equivT, nested.second.front(),
41654144
*this);
@@ -4252,35 +4231,39 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirement(
42524231
}
42534232

42544233
ConstraintResult GenericSignatureBuilder::addSameTypeRequirementDirect(
4255-
ResolvedType paOrT1, ResolvedType paOrT2,
4234+
ResolvedType type1, ResolvedType type2,
42564235
FloatingRequirementSource source,
42574236
llvm::function_ref<void(Type, Type)> diagnoseMismatch) {
4258-
// FIXME: Realizes potential archetypes far too early.
4259-
auto t1 = paOrT1.getAsConcreteType();
4260-
auto *pa1 = t1 ? nullptr : paOrT1.realizePotentialArchetype(*this);
4261-
4262-
auto t2 = paOrT2.getAsConcreteType();
4263-
auto *pa2 = t2 ? nullptr : paOrT2.realizePotentialArchetype(*this);
4264-
4265-
// If both sides of the requirement are type parameters, equate them.
4266-
if (pa1 && pa2) {
4267-
return addSameTypeRequirementBetweenArchetypes(
4268-
pa1, pa2,
4269-
source.getSource(*this,
4270-
paOrT2.getDependentType(*this)));
4271-
// If just one side is a type parameter, map it to a concrete type.
4272-
} else if (pa1) {
4273-
return addSameTypeRequirementToConcrete(
4274-
pa1, t2,
4275-
source.getSource(*this, paOrT1.getDependentType(*this)));
4276-
} else if (pa2) {
4277-
return addSameTypeRequirementToConcrete(
4278-
pa2, t1,
4279-
source.getSource(*this, paOrT2.getDependentType(*this)));
4280-
} else {
4281-
return addSameTypeRequirementBetweenConcrete(t1, t2, source,
4237+
auto concreteType1 = type1.getAsConcreteType();
4238+
auto concreteType2 = type2.getAsConcreteType();
4239+
4240+
// If both sides of the requirement are concrete, equate them.
4241+
if (concreteType1 && concreteType2) {
4242+
return addSameTypeRequirementBetweenConcrete(concreteType1,
4243+
concreteType2, source,
42824244
diagnoseMismatch);
42834245
}
4246+
4247+
// If one side is concrete, map the other side to that concrete type.
4248+
if (concreteType1) {
4249+
return addSameTypeRequirementToConcrete(type2, concreteType1,
4250+
source.getSource(*this, type2.getDependentType(*this)));
4251+
}
4252+
4253+
if (concreteType2) {
4254+
return addSameTypeRequirementToConcrete(type1, concreteType2,
4255+
source.getSource(*this, type1.getDependentType(*this)));
4256+
}
4257+
4258+
// Both sides are type parameters; equate them.
4259+
// FIXME: Realizes potential archetypes far too early.
4260+
auto pa1 = type1.realizePotentialArchetype(*this);
4261+
auto pa2 = type2.realizePotentialArchetype(*this);
4262+
4263+
return addSameTypeRequirementBetweenArchetypes(
4264+
pa1, pa2,
4265+
source.getSource(*this,
4266+
type2.getDependentType(*this)));
42844267
}
42854268

42864269
ConstraintResult GenericSignatureBuilder::addInheritedRequirements(
@@ -5435,7 +5418,7 @@ static bool unionSets(SmallVectorImpl<unsigned> &parents,
54355418
static void computeDerivedSameTypeComponents(
54365419
GenericSignatureBuilder &builder,
54375420
EquivalenceClass *equivClass,
5438-
llvm::SmallDenseMap<PotentialArchetype *, unsigned> &componentOf){
5421+
llvm::SmallDenseMap<CanType, unsigned> &componentOf){
54395422
// Set up the array of "parents" in the union-find data structure.
54405423
llvm::SmallDenseMap<CanType, unsigned> parentIndices;
54415424
SmallVector<unsigned, 4> parents;
@@ -5478,18 +5461,20 @@ static void computeDerivedSameTypeComponents(
54785461

54795462
// If this is the representative, add a component for it.
54805463
if (representative == index) {
5481-
componentOf[pa] = components.size();
5464+
componentOf[depType] = components.size();
54825465
components.push_back(DerivedSameTypeComponent{pa, nullptr});
54835466
continue;
54845467
}
54855468

54865469
// This is not the representative; point at the component of the
54875470
// representative.
5488-
auto representativePA = equivClass->members[representative];
5489-
assert(componentOf.count(representativePA) == 1 &&
5471+
CanType representativeDepTy =
5472+
equivClass->members[representative]->getDependentType({ })
5473+
->getCanonicalType();
5474+
assert(componentOf.count(representativeDepTy) == 1 &&
54905475
"Missing representative component?");
5491-
unsigned componentIndex = componentOf[representativePA];
5492-
componentOf[pa] = componentIndex;
5476+
unsigned componentIndex = componentOf[representativeDepTy];
5477+
componentOf[depType] = componentIndex;
54935478

54945479
// If this is a better anchor, record it.
54955480
if (compareDependentTypes(&pa, &components[componentIndex].anchor) < 0)
@@ -5498,13 +5483,12 @@ static void computeDerivedSameTypeComponents(
54985483

54995484
// If there is a concrete type, figure out the best concrete type anchor
55005485
// per component.
5486+
auto genericParams = builder.getGenericParams();
55015487
for (const auto &concrete : equivClass->concreteTypeConstraints) {
55025488
// Dig out the component associated with constraint.
5503-
Type subjectType =
5504-
concrete.getSubjectDependentType(builder.getGenericParams());
5505-
auto subjectPA = concrete.realizeSubjectPotentialArchetype(builder);
5506-
assert(componentOf.count(subjectPA) > 0);
5507-
auto &component = components[componentOf[subjectPA]];
5489+
Type subjectType = concrete.getSubjectDependentType(genericParams);
5490+
assert(componentOf.count(subjectType->getCanonicalType()) > 0);
5491+
auto &component = components[componentOf[subjectType->getCanonicalType()]];
55085492

55095493
// FIXME: Skip self-derived sources. This means our attempts to "stage"
55105494
// construction of self-derived sources really don't work, because we
@@ -5573,16 +5557,17 @@ void IntercomponentEdge::dump() const {
55735557
/// nodes \c from and \c to within the given equivalence class.
55745558
static bool removalDisconnectsEquivalenceClass(
55755559
EquivalenceClass *equivClass,
5576-
llvm::SmallDenseMap<PotentialArchetype *, unsigned> &componentOf,
5560+
llvm::SmallDenseMap<CanType, unsigned> &componentOf,
55775561
std::vector<IntercomponentEdge> &sameTypeEdges,
55785562
unsigned edgeIndex,
5579-
PotentialArchetype *from,
5580-
PotentialArchetype *to) {
5563+
CanType fromDepType,
5564+
CanType toDepType) {
55815565
// Which component are "from" and "to" in within the intercomponent edges?
5582-
assert(componentOf.count(from) > 0);
5583-
auto fromComponentIndex = componentOf[from];
5584-
assert(componentOf.count(to) > 0);
5585-
auto toComponentIndex = componentOf[to];
5566+
assert(componentOf.count(fromDepType) > 0);
5567+
auto fromComponentIndex = componentOf[fromDepType];
5568+
5569+
assert(componentOf.count(toDepType) > 0);
5570+
auto toComponentIndex = componentOf[toDepType];
55865571

55875572
// If they're in the same component, they're always connected (due to
55885573
// derived edges).
@@ -5616,24 +5601,33 @@ static bool removalDisconnectsEquivalenceClass(
56165601
static bool isSelfDerivedNestedTypeNameMatchEdge(
56175602
GenericSignatureBuilder &builder,
56185603
EquivalenceClass *equivClass,
5619-
llvm::SmallDenseMap<PotentialArchetype *, unsigned> &componentOf,
5604+
llvm::SmallDenseMap<CanType, unsigned> &componentOf,
56205605
std::vector<IntercomponentEdge> &sameTypeEdges,
56215606
unsigned edgeIndex) {
56225607
const auto &edge = sameTypeEdges[edgeIndex];
5623-
PotentialArchetype *source =
5624-
edge.constraint.realizeSubjectPotentialArchetype(builder);
5608+
auto genericParams = builder.getGenericParams();
5609+
Type sourceType = edge.constraint.getSubjectDependentType(genericParams);
56255610
PotentialArchetype *target = edge.constraint.value;
5626-
while (source->getParent() && target->getParent() &&
5627-
source->getResolvedAssociatedType() ==
5628-
target->getResolvedAssociatedType()) {
5629-
source = source->getParent();
5611+
5612+
DependentMemberType *sourceDepMemTy;
5613+
while ((sourceDepMemTy = sourceType->getAs<DependentMemberType>()) &&
5614+
target->getParent() &&
5615+
sourceDepMemTy->getAssocType() &&
5616+
sourceDepMemTy->getAssocType() == target->getResolvedAssociatedType()){
5617+
sourceType = sourceDepMemTy->getBase();
56305618
target = target->getParent();
56315619

5632-
if (source->isInSameEquivalenceClassAs(target) &&
5633-
source->getEquivalenceClassIfPresent() == equivClass &&
5620+
if (target->getEquivalenceClassIfPresent() == equivClass &&
5621+
builder.maybeResolveEquivalenceClass(
5622+
sourceType,
5623+
ArchetypeResolutionKind::WellFormed,
5624+
/*wantExactPotentialArchetype=*/false)
5625+
.getEquivalenceClass(builder) == equivClass &&
56345626
!removalDisconnectsEquivalenceClass(equivClass, componentOf,
56355627
sameTypeEdges, edgeIndex,
5636-
source, target))
5628+
sourceType->getCanonicalType(),
5629+
target->getDependentType({ })
5630+
->getCanonicalType()))
56375631
return true;
56385632
}
56395633

@@ -5648,7 +5642,7 @@ static bool isSelfDerivedNestedTypeNameMatchEdge(
56485642
static void collapseSameTypeComponentsThroughDelayedRequirements(
56495643
GenericSignatureBuilder &builder,
56505644
EquivalenceClass *equivClass,
5651-
llvm::SmallDenseMap<PotentialArchetype *, unsigned> &componentOf,
5645+
llvm::SmallDenseMap<CanType, unsigned> &componentOf,
56525646
SmallVectorImpl<unsigned> &collapsedParents,
56535647
unsigned &remainingComponents) {
56545648
unsigned numCollapsedParents = collapsedParents.size();
@@ -5660,6 +5654,10 @@ static void collapseSameTypeComponentsThroughDelayedRequirements(
56605654
/// Retrieve the component for a type representing a virtual component
56615655
auto getTypeVirtualComponent = [&](Type type) {
56625656
CanType canType = type->getCanonicalType();
5657+
auto knownActual = componentOf.find(canType);
5658+
if (knownActual != componentOf.end())
5659+
return knownActual->second;
5660+
56635661
auto knownVirtual = virtualComponents.find(canType);
56645662
if (knownVirtual != virtualComponents.end())
56655663
return knownVirtual->second;
@@ -5671,32 +5669,18 @@ static void collapseSameTypeComponentsThroughDelayedRequirements(
56715669
};
56725670

56735671
/// Retrieve the component for the given potential archetype.
5672+
auto genericParams = builder.getGenericParams();
56745673
auto getPotentialArchetypeVirtualComponent = [&](PotentialArchetype *pa) {
56755674
if (pa->getEquivalenceClassIfPresent() == equivClass)
5676-
return componentOf[pa];
5675+
return getTypeVirtualComponent(pa->getDependentType(genericParams));
56775676

56785677
// We found a potential archetype in another equivalence class. Treat it
56795678
// as a "virtual" component representing that potential archetype's
56805679
// equivalence class.
5681-
auto genericParams = builder.getGenericParams();
56825680
return getTypeVirtualComponent(
56835681
pa->getRepresentative()->getDependentType(genericParams));
56845682
};
56855683

5686-
/// Local function to retrieve the component with which the given type is
5687-
/// associated, for a type that we haven't tried to resolve yet.
5688-
auto getUnknownTypeVirtualComponent = [&](Type type) {
5689-
if (auto pa =
5690-
builder.maybeResolveEquivalenceClass(
5691-
type,
5692-
ArchetypeResolutionKind::AlreadyKnown,
5693-
/*wantExactPotentialArchetype=*/true)
5694-
.getPotentialArchetypeIfKnown())
5695-
return getPotentialArchetypeVirtualComponent(pa);
5696-
5697-
return getTypeVirtualComponent(type);
5698-
};
5699-
57005684
for (const auto &delayedReq : equivClass->delayedRequirements) {
57015685
// Only consider same-type requirements.
57025686
if (delayedReq.kind != DelayedRequirement::SameType) continue;
@@ -5705,13 +5689,13 @@ static void collapseSameTypeComponentsThroughDelayedRequirements(
57055689
if (auto lhsPA = delayedReq.lhs.dyn_cast<PotentialArchetype *>())
57065690
lhsComponent = getPotentialArchetypeVirtualComponent(lhsPA);
57075691
else
5708-
lhsComponent = getUnknownTypeVirtualComponent(delayedReq.lhs.get<Type>());
5692+
lhsComponent = getTypeVirtualComponent(delayedReq.lhs.get<Type>());
57095693

57105694
unsigned rhsComponent;
57115695
if (auto rhsPA = delayedReq.rhs.dyn_cast<PotentialArchetype *>())
57125696
rhsComponent = getPotentialArchetypeVirtualComponent(rhsPA);
57135697
else
5714-
rhsComponent = getUnknownTypeVirtualComponent(delayedReq.rhs.get<Type>());
5698+
rhsComponent = getTypeVirtualComponent(delayedReq.rhs.get<Type>());
57155699

57165700
// Collapse the sets
57175701
if (unionSets(collapsedParents, lhsComponent, rhsComponent,
@@ -5731,7 +5715,7 @@ static void collapseSameTypeComponentsThroughDelayedRequirements(
57315715
static void collapseSameTypeComponents(
57325716
GenericSignatureBuilder &builder,
57335717
EquivalenceClass *equivClass,
5734-
llvm::SmallDenseMap<PotentialArchetype *, unsigned> &componentOf,
5718+
llvm::SmallDenseMap<CanType, unsigned> &componentOf,
57355719
std::vector<IntercomponentEdge> &sameTypeEdges) {
57365720
SmallVector<unsigned, 4> collapsedParents;
57375721
for (unsigned i : indices(equivClass->derivedSameTypeComponents)) {
@@ -5851,7 +5835,7 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
58515835

58525836
// Compute the components in the subgraph of the same-type constraint graph
58535837
// that includes only derived constraints.
5854-
llvm::SmallDenseMap<PotentialArchetype *, unsigned> componentOf;
5838+
llvm::SmallDenseMap<CanType, unsigned> componentOf;
58555839
computeDerivedSameTypeComponents(*this, equivClass, componentOf);
58565840

58575841
// Go through all of the same-type constraints, collecting all of the
@@ -5883,13 +5867,16 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
58835867
}
58845868

58855869
// Determine which component each of the source/destination fall into.
5886-
auto subjectPA = constraint.realizeSubjectPotentialArchetype(*this);
5887-
assert(componentOf.count(subjectPA) > 0 &&
5870+
CanType subjectType =
5871+
constraint.getSubjectDependentType({ })->getCanonicalType();
5872+
assert(componentOf.count(subjectType) > 0 &&
58885873
"unknown potential archetype?");
5889-
unsigned firstComponentIdx = componentOf[subjectPA];
5890-
assert(componentOf.count(constraint.value) > 0 &&
5874+
unsigned firstComponentIdx = componentOf[subjectType];
5875+
assert(componentOf.count(
5876+
constraint.value->getDependentType({ })->getCanonicalType()) > 0 &&
58915877
"unknown potential archetype?");
5892-
unsigned secondComponentIdx = componentOf[constraint.value];
5878+
unsigned secondComponentIdx =
5879+
componentOf[constraint.value->getDependentType({ })->getCanonicalType()];
58935880

58945881
// Separately track nested-type-name-match constraints.
58955882
if (constraint.source->getRoot()->kind ==

0 commit comments

Comments
 (0)