Skip to content

Commit 0eedacf

Browse files
committed
[GSB] Use anchors for the keys in the mapping to rewrite tree roots.
Rather than keying the rewrite tree roots on equivalence classes, which imply a mapping through potential archetypes, key on (canonical) types that are currently the anchors of equivalence classes.
1 parent 35902bb commit 0eedacf

File tree

1 file changed

+45
-36
lines changed

1 file changed

+45
-36
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,9 @@ struct GenericSignatureBuilder::Implementation {
437437
/// Equivalence classes that are not currently being used.
438438
std::vector<void *> FreeEquivalenceClasses;
439439

440-
/// The roots of the rewrite tree.
441-
DenseMap<const EquivalenceClass *, std::unique_ptr<RewriteTreeNode>>
442-
RewriteTreeRoots;
440+
/// The roots of the rewrite tree, keyed on the canonical types of the
441+
/// anchors.
442+
DenseMap<CanType, std::unique_ptr<RewriteTreeNode>> RewriteTreeRoots;
443443

444444
/// The generation number for the term-rewriting system, which is
445445
/// increased every time a new rule gets added.
@@ -482,15 +482,12 @@ struct GenericSignatureBuilder::Implementation {
482482
/// Deallocate the given equivalence class, returning it to the free list.
483483
void deallocateEquivalenceClass(EquivalenceClass *equivClass);
484484

485-
/// Retrieve the rewrite tree root for the given equivalence class,
486-
/// if present.
487-
RewriteTreeNode *getRewriteTreeRootIfPresent(
488-
const EquivalenceClass *equivClass);
485+
/// Retrieve the rewrite tree root for the given anchor type.
486+
RewriteTreeNode *getRewriteTreeRootIfPresent(CanType anchor);
489487

490-
/// Retrieve the rewrite tree root for the given equivalence class,
488+
/// Retrieve the rewrite tree root for the given anchor type,
491489
/// creating it if needed.
492-
RewriteTreeNode *getOrCreateRewriteTreeRoot(
493-
const EquivalenceClass *equivClass);
490+
RewriteTreeNode *getOrCreateRewriteTreeRoot(CanType anchor);
494491

495492
/// Minimize the rewrite tree by minimizing the right-hand sides and
496493
/// removing redundant rules.
@@ -2493,7 +2490,11 @@ void EquivalenceClass::dump(llvm::raw_ostream &out,
24932490
out << "\n";
24942491

24952492
if (builder) {
2496-
if (auto rewriteRoot = builder->Impl->getRewriteTreeRootIfPresent(this)) {
2493+
CanType anchorType =
2494+
const_cast<EquivalenceClass *>(this)->getAnchor(*builder, { })
2495+
->getCanonicalType();
2496+
if (auto rewriteRoot =
2497+
builder->Impl->getRewriteTreeRootIfPresent(anchorType)) {
24972498
out << "---Rewrite tree---\n";
24982499
rewriteRoot->dump(out);
24992500
}
@@ -3543,20 +3544,20 @@ void RewriteTreeNode::dump(llvm::raw_ostream &out, bool lastChild) const {
35433544

35443545
RewriteTreeNode *
35453546
GenericSignatureBuilder::Implementation::getRewriteTreeRootIfPresent(
3546-
const EquivalenceClass *equivClass) {
3547-
auto known = RewriteTreeRoots.find(equivClass);
3547+
CanType anchor) {
3548+
auto known = RewriteTreeRoots.find(anchor);
35483549
if (known != RewriteTreeRoots.end()) return known->second.get();
35493550

35503551
return nullptr;
35513552
}
35523553

35533554
RewriteTreeNode *
35543555
GenericSignatureBuilder::Implementation::getOrCreateRewriteTreeRoot(
3555-
const EquivalenceClass *equivClass) {
3556-
auto known = RewriteTreeRoots.find(equivClass);
3556+
CanType anchor) {
3557+
auto known = RewriteTreeRoots.find(anchor);
35573558
if (known != RewriteTreeRoots.end()) return known->second.get();
35583559

3559-
auto &root = RewriteTreeRoots[equivClass];
3560+
auto &root = RewriteTreeRoots[anchor];
35603561
root = std::unique_ptr<RewriteTreeNode>(new RewriteTreeNode(nullptr));
35613562
return root.get();
35623563
}
@@ -3585,7 +3586,8 @@ void GenericSignatureBuilder::Implementation::minimizeRewriteTreeRhs(
35853586

35863587
// Minimize the right-hand sides of each rule in the tree.
35873588
for (auto &equivClass : EquivalenceClasses) {
3588-
auto root = RewriteTreeRoots.find(&equivClass);
3589+
CanType anchorType = equivClass.getAnchor(builder, { })->getCanonicalType();
3590+
auto root = RewriteTreeRoots.find(anchorType);
35893591
if (root == RewriteTreeRoots.end()) continue;
35903592

35913593
AnchorPathCache anchorPathCache(builder, equivClass);
@@ -3640,7 +3642,8 @@ void GenericSignatureBuilder::Implementation::removeRewriteTreeRedundancies(
36403642

36413643
// Minimize the right-hand sides of each rule in the tree.
36423644
for (auto &equivClass : EquivalenceClasses) {
3643-
auto root = RewriteTreeRoots.find(&equivClass);
3645+
CanType anchorType = equivClass.getAnchor(builder, { })->getCanonicalType();
3646+
auto root = RewriteTreeRoots.find(anchorType);
36443647
if (root == RewriteTreeRoots.end()) continue;
36453648

36463649
AnchorPathCache anchorPathCache(builder, equivClass);
@@ -3701,14 +3704,13 @@ bool GenericSignatureBuilder::addSameTypeRewriteRule(
37013704
if (compareDependentPaths(relPath1, relPath2) < 0)
37023705
std::swap(relPath1, relPath2);
37033706

3704-
// Find the equivalence class for the prefix.
3707+
// Find the anchor for the prefix.
37053708
CanType commonType = prefix.formDependentType(getASTContext());
3706-
auto equivClass =
3707-
resolveEquivalenceClass(commonType, ArchetypeResolutionKind::WellFormed);
3708-
assert(equivClass && "Prefix cannot be resolved?");
3709+
CanType commonAnchor =
3710+
getCanonicalTypeParameter(commonType)->getCanonicalType();
37093711

37103712
// Add the rewrite rule.
3711-
auto root = Impl->getOrCreateRewriteTreeRoot(equivClass);
3713+
auto root = Impl->getOrCreateRewriteTreeRoot(commonAnchor);
37123714
return root->addRewriteRule(
37133715
relPath1,
37143716
RewritePath(None, relPath2, RewritePath::Forward));
@@ -3726,11 +3728,9 @@ bool GenericSignatureBuilder::addSameTypeRewriteRule(
37263728
Type firstBase =
37273729
GenericTypeParamType::get(path1.getBase()->Depth, path1.getBase()->Index,
37283730
getASTContext());
3729-
auto baseEquivClass =
3730-
resolveEquivalenceClass(firstBase, ArchetypeResolutionKind::WellFormed);
3731-
assert(baseEquivClass && "Base cannot be resolved?");
3732-
3733-
auto root = Impl->getOrCreateRewriteTreeRoot(baseEquivClass);
3731+
CanType baseAnchor =
3732+
getCanonicalTypeParameter(firstBase)->getCanonicalType();
3733+
auto root = Impl->getOrCreateRewriteTreeRoot(baseAnchor);
37343734
return root->addRewriteRule(path1.getPath(), path2);
37353735
}
37363736

@@ -3752,7 +3752,8 @@ Type GenericSignatureBuilder::getCanonicalTypeParameter(Type type) {
37523752
initialPath.getPath().end());
37533753
bool simplified = false;
37543754
do {
3755-
if (auto rootNode = Impl->getRewriteTreeRootIfPresent(equivClass)) {
3755+
CanType currentAnchor = currentType->getCanonicalType();
3756+
if (auto rootNode = Impl->getRewriteTreeRootIfPresent(currentAnchor)) {
37563757
// Find the best rewrite rule for the path starting at startIndex.
37573758
auto match =
37583759
rootNode->bestRewritePath(genericParamType,
@@ -4876,8 +4877,17 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
48764877
std::swap(OrigT1, OrigT2);
48774878
}
48784879

4879-
// Add a rewrite rule to map T2 down to the anchor.
48804880
auto equivClass = T1->getOrCreateEquivalenceClass(*this);
4881+
auto equivClass2 = T2->getEquivalenceClassIfPresent();
4882+
4883+
// Determine the anchor types of the two equivalence classes.
4884+
CanType anchor1 = equivClass->getAnchor(*this, { })->getCanonicalType();
4885+
CanType anchor2 =
4886+
(equivClass2 ? equivClass2->getAnchor(*this, { })
4887+
: getCanonicalTypeParameter(T2->getDependentType({ })))
4888+
->getCanonicalType();
4889+
4890+
// Add a rewrite rule to map T2 down to the anchor.
48814891
if (addSameTypeRewriteRule(equivClass, T2))
48824892
++Impl->RewriteGeneration;
48834893

@@ -4889,7 +4899,6 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
48894899
equivClass->addMember(equiv);
48904900

48914901
// Grab the old equivalence class, if present. We'll deallocate it at the end.
4892-
auto equivClass2 = T2->getEquivalenceClassIfPresent();
48934902
SWIFT_DEFER {
48944903
if (equivClass2)
48954904
Impl->deallocateEquivalenceClass(equivClass2);
@@ -4907,18 +4916,18 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
49074916
equivClass2->sameTypeConstraints.end());
49084917

49094918
// Combine the rewrite rules.
4910-
if (auto rewriteRoot2 = Impl->getOrCreateRewriteTreeRoot(equivClass2)) {
4911-
if (auto rewriteRoot1 = Impl->getOrCreateRewriteTreeRoot(equivClass)) {
4919+
if (auto rewriteRoot2 = Impl->getOrCreateRewriteTreeRoot(anchor2)) {
4920+
if (auto rewriteRoot1 = Impl->getOrCreateRewriteTreeRoot(anchor1)) {
49124921
// Merge the second rewrite tree into the first.
49134922
if (rewriteRoot2->mergeInto(rewriteRoot1))
49144923
++Impl->RewriteGeneration;
4915-
Impl->RewriteTreeRoots.erase(equivClass2);
4924+
Impl->RewriteTreeRoots.erase(anchor2);
49164925
} else {
49174926
// Take the second rewrite tree and make it the first.
4918-
auto root2Entry = Impl->RewriteTreeRoots.find(equivClass2);
4927+
auto root2Entry = Impl->RewriteTreeRoots.find(anchor2);
49194928
auto root2Ptr = std::move(root2Entry->second);
49204929
Impl->RewriteTreeRoots.erase(root2Entry);
4921-
(void)Impl->RewriteTreeRoots.insert({equivClass, std::move(root2Ptr)});
4930+
(void)Impl->RewriteTreeRoots.insert({anchor1, std::move(root2Ptr)});
49224931
}
49234932
}
49244933
}

0 commit comments

Comments
 (0)