Skip to content

Commit 3184dd8

Browse files
authored
Merge pull request #14685 from DougGregor/gsb-rewrite-rule-anchor
[GSB] Ensure that term rewriting rules produce correct anchors
2 parents 0ec1cd7 + bd266b0 commit 3184dd8

File tree

4 files changed

+62
-54
lines changed

4 files changed

+62
-54
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -445,10 +445,10 @@ class GenericSignatureBuilder {
445445
/// Note that we have added the nested type nestedPA
446446
void addedNestedType(PotentialArchetype *nestedPA);
447447

448-
/// Add a rewrite rule for a same-type constraint between the given
449-
/// types.
450-
void addSameTypeRewriteRule(PotentialArchetype *type1,
451-
PotentialArchetype *type2);
448+
/// Add a rewrite rule that makes \c otherPA a part of the given equivalence
449+
/// class.
450+
void addSameTypeRewriteRule(EquivalenceClass *equivClass,
451+
PotentialArchetype *otherPA);
452452

453453
/// \brief Add a new conformance requirement specifying that the given
454454
/// potential archetypes are equivalent.

lib/AST/GenericSignature.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,7 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
11201120
if (source->kind == RequirementSource::Superclass ||
11211121
source->kind == RequirementSource::Concrete) {
11221122
auto conformance = source->getProtocolConformance();
1123+
(void)conformance;
11231124
assert(conformance.getRequirement() == conformingProto);
11241125
path.path.push_back({source->getAffectedType(), conformingProto});
11251126
return;

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,6 @@ STATISTIC(NumDelayedRequirementUnresolved,
107107
"Delayed requirements left unresolved");
108108
STATISTIC(NumConditionalRequirementsAdded,
109109
"# of conditional requirements added");
110-
STATISTIC(NumComponentsCollapsedViaRewriting,
111-
"# of same-type components collapsed via term rewriting");
112110

113111
namespace {
114112

@@ -412,10 +410,6 @@ namespace {
412410
BaseIterator base;
413411
BaseIterator baseEnd;
414412

415-
void advance() {
416-
++base;
417-
}
418-
419413
public:
420414
using difference_type = ptrdiff_t;
421415
using value_type = EquivalenceClassVizNode;
@@ -426,7 +420,6 @@ namespace {
426420
EquivalenceClassVizIterator(EquivalenceClassVizNode node,
427421
BaseIterator base, BaseIterator baseEnd)
428422
: node(node), base(base), baseEnd(baseEnd) {
429-
advance();
430423
}
431424

432425
BaseIterator &getBase() { return base; }
@@ -438,7 +431,6 @@ namespace {
438431

439432
EquivalenceClassVizIterator& operator++() {
440433
++getBase();
441-
advance();
442434
return *this;
443435
}
444436

@@ -2157,19 +2149,42 @@ Type EquivalenceClass::getAnchor(
21572149
}
21582150

21592151
// Form the anchor.
2152+
bool updatedAnchor = false;
21602153
for (auto member : members) {
21612154
auto anchorType =
21622155
builder.getCanonicalTypeParameter(member->getDependentType(genericParams));
21632156
if (!anchorType) continue;
21642157

2158+
#ifndef NDEBUG
2159+
// Check that we get consistent results from all of the anchors.
2160+
if (updatedAnchor) {
2161+
assert(anchorType->isEqual(archetypeAnchorCache.anchor) &&
2162+
"Inconsistent anchor computation");
2163+
continue;
2164+
}
2165+
#endif
2166+
21652167
// Record the cache miss and update the cache.
21662168
++NumArchetypeAnchorCacheMisses;
21672169
archetypeAnchorCache.anchor = anchorType;
21682170
archetypeAnchorCache.lastGeneration = builder.Impl->Generation;
2169-
return substAnchor();
2171+
updatedAnchor = true;
2172+
2173+
#if NDEBUG
2174+
break;
2175+
#endif
21702176
}
21712177

2172-
llvm_unreachable("Unable to compute anchor");
2178+
// FIXME: Once we are no longer constructing potential archetypes with
2179+
// concrete nested types, we can turn this into assert(updatedAnchor);
2180+
if (!updatedAnchor) {
2181+
++NumArchetypeAnchorCacheMisses;
2182+
archetypeAnchorCache.anchor =
2183+
builder.getCanonicalTypeParameter(members.front()->getDependentType({ }));
2184+
archetypeAnchorCache.lastGeneration = builder.Impl->Generation;
2185+
}
2186+
2187+
return substAnchor();
21732188
}
21742189

21752190
Type EquivalenceClass::getTypeInContext(GenericSignatureBuilder &builder,
@@ -3299,17 +3314,19 @@ RewriteTreeNode::bestMatch(GenericParamKey base, RelativeRewritePath path,
32993314
[&](unsigned length, RewritePath path) {
33003315
// Determine how much of the original path will be replaced by the rewrite.
33013316
unsigned adjustedLength = length;
3317+
bool changesBase = false;
33023318
if (auto newBase = path.getBase()) {
33033319
adjustedLength += prefixLength;
33043320

33053321
// If the base is unchanged, make sure we're reducing the length.
3306-
if (*newBase == base && adjustedLength <= path.getPath().size())
3322+
changesBase = *newBase != base;
3323+
if (!changesBase && adjustedLength <= path.getPath().size())
33073324
return;
33083325
}
33093326

3310-
if (adjustedLength == 0) return;
3327+
if (adjustedLength == 0 && !changesBase) return;
33113328

3312-
if (adjustedLength > bestAdjustedLength ||
3329+
if (adjustedLength > bestAdjustedLength || !best ||
33133330
(adjustedLength == bestAdjustedLength &&
33143331
path.compare(best->second) < 0)) {
33153332
best = { length, path };
@@ -3407,39 +3424,29 @@ GenericSignatureBuilder::Implementation::getOrCreateRewriteTreeRoot(
34073424
return root;
34083425
}
34093426

3410-
void GenericSignatureBuilder::addSameTypeRewriteRule(PotentialArchetype *pa1,
3411-
PotentialArchetype *pa2){
3412-
auto pathOpt1 = RewritePath::createPath(pa1);
3413-
if (!pathOpt1) return;
3414-
3415-
auto pathOpt2 = RewritePath::createPath(pa2);
3416-
if (!pathOpt2) return;
3417-
3418-
auto path1 = std::move(pathOpt1).getValue();
3419-
auto path2 = std::move(pathOpt2).getValue();
3427+
void GenericSignatureBuilder::addSameTypeRewriteRule(
3428+
EquivalenceClass *equivClass,
3429+
PotentialArchetype *otherPA){
3430+
// Simplify both sides in the hope of uncovering a common path.
3431+
Type simplifiedType1 = equivClass->getAnchor(*this, { });
3432+
if (!simplifiedType1) return;
34203433

3421-
// Look for a common path.
3422-
auto prefix = path1.commonPath(path2);
3423-
3424-
// If we didn't find a common path, try harder.
3425-
Type simplifiedType1;
34263434
Type simplifiedType2;
3427-
if (!prefix) {
3428-
// Simplify both sides in the hope of uncovering a common path.
3429-
simplifiedType1 = getCanonicalTypeParameter(pa1->getDependentType({ }));
3430-
simplifiedType2 = getCanonicalTypeParameter(pa2->getDependentType({ }));
3431-
if (simplifiedType1->isEqual(simplifiedType2)) return;
3435+
if (auto otherEquivClass = otherPA->getEquivalenceClassIfPresent())
3436+
simplifiedType2 = otherEquivClass->getAnchor(*this, { });
3437+
else
3438+
simplifiedType2 = getCanonicalTypeParameter(otherPA->getDependentType({ }));
3439+
if (!simplifiedType2) return;
34323440

3433-
// Create new paths from the simplified types.
3434-
path1 = *RewritePath::createPath(simplifiedType1);
3435-
path2 = *RewritePath::createPath(simplifiedType2);
3441+
// We already effectively have this rewrite rule.
3442+
if (simplifiedType1->isEqual(simplifiedType2)) return;
34363443

3437-
// Find a common path.
3438-
prefix = path1.commonPath(path2);
3439-
}
3444+
auto path1 = *RewritePath::createPath(simplifiedType1);
3445+
auto path2 = *RewritePath::createPath(simplifiedType2);
34403446

3441-
// When we have a common prefix, form a rewrite rule using relative paths.
3442-
if (prefix) {
3447+
// Look for a common prefix. When we have one, form a rewrite rule using
3448+
// relative paths.
3449+
if (auto prefix = path1.commonPath(path2)) {
34433450
// Find the better relative rewrite path.
34443451
RelativeRewritePath relPath1
34453452
= path1.getPath().slice(prefix->getPath().size());
@@ -3475,11 +3482,11 @@ void GenericSignatureBuilder::addSameTypeRewriteRule(PotentialArchetype *pa1,
34753482
Type firstBase =
34763483
GenericTypeParamType::get(path1.getBase()->Depth, path1.getBase()->Index,
34773484
getASTContext());
3478-
auto equivClass =
3485+
auto baseEquivClass =
34793486
resolveEquivalenceClass(firstBase, ArchetypeResolutionKind::WellFormed);
3480-
assert(equivClass && "Base cannot be resolved?");
3487+
assert(baseEquivClass && "Base cannot be resolved?");
34813488

3482-
auto root = Impl->getOrCreateRewriteTreeRoot(equivClass);
3489+
auto root = Impl->getOrCreateRewriteTreeRoot(baseEquivClass);
34833490
root->addRewriteRule(path1.getPath(), path2);
34843491
}
34853492

@@ -3842,6 +3849,7 @@ bool GenericSignatureBuilder::addGenericParameterRequirements(
38423849
void GenericSignatureBuilder::addGenericParameter(GenericTypeParamType *GenericParam) {
38433850
GenericParamKey Key(GenericParam);
38443851
auto params = getGenericParams();
3852+
(void)params;
38453853
assert(params.empty() ||
38463854
((Key.Depth == params.back()->getDepth() &&
38473855
Key.Index == params.back()->getIndex() + 1) ||
@@ -4544,9 +4552,6 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
45444552
PotentialArchetype *OrigT2,
45454553
const RequirementSource *Source)
45464554
{
4547-
// Add a rewrite rule based on the given same-type constraint.
4548-
addSameTypeRewriteRule(OrigT1, OrigT2);
4549-
45504555
// Record the same-type constraint, and bail out if it was already known.
45514556
if (!OrigT1->getOrCreateEquivalenceClass(*this)
45524557
->recordSameTypeConstraint(OrigT1, OrigT2, Source))
@@ -4566,10 +4571,12 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
45664571
std::swap(OrigT1, OrigT2);
45674572
}
45684573

4569-
// Merge the equivalence classes.
4574+
// Add a rewrite rule to map T2 down to the anchor.
45704575
auto equivClass = T1->getOrCreateEquivalenceClass(*this);
4571-
equivClass->modified(*this);
4576+
addSameTypeRewriteRule(equivClass, T2);
45724577

4578+
// Merge the equivalence classes.
4579+
equivClass->modified(*this);
45734580
auto equivClass1Members = equivClass->members;
45744581
auto equivClass2Members = T2->getEquivalenceClassMembers();
45754582
for (auto equiv : equivClass2Members)

test/Generics/sr5726.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ protocol Foo
77
var bar: Bar { get }
88
}
99

10-
extension Foo where Self: Collection, Bar: Collection, Self.SubSequence == Bar.SubSequence, Self.Index == Bar.Index
10+
extension Foo where Self: Collection, Bar: Collection, Self.SubSequence == Bar.SubSequence, /*redundant: */Self.Index == Bar.Index
1111
{
1212
subscript(_ bounds: Range<Index>) -> SubSequence
1313
{

0 commit comments

Comments
 (0)