Skip to content

Commit ded45a6

Browse files
committed
[GSB] SE-0157: Reprocess delayed requirements when we need a complete PA.
Whenever we need a complete, well-formed potential archetype, reprocess any delayed requirements, so that we pick up additional requirements on that potential archetype. This relies on us tracking a generation count for the GSB instance as a whole, which gets bumped each time we add some new requirement or create a new potential archetype, and only actually reprocessing delayed requirements when the generation count exceeds the point at which we last processed delayed requirements. This gets the most basic recursive protocol constraint working end-to-end and doesn't seem to break things.
1 parent f7ee425 commit ded45a6

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ struct GenericSignatureBuilder::Implementation {
9090
/// The set of requirements that have been delayed for some reason.
9191
SmallVector<DelayedRequirement, 4> DelayedRequirements;
9292

93+
/// The generation number, which is incremented whenever we successfully
94+
/// introduce a new constraint.
95+
unsigned Generation = 0;
96+
97+
/// The generation at which we last processed all of the delayed requirements.
98+
unsigned LastProcessedGeneration = 0;
99+
93100
#ifndef NDEBUG
94101
/// Whether we've already finalized the builder.
95102
bool finalized = false;
@@ -1399,6 +1406,9 @@ bool PotentialArchetype::addConformance(ProtocolDecl *proto,
13991406
return false;
14001407
}
14011408

1409+
// Bump the generation.
1410+
++builder.Impl->Generation;
1411+
14021412
// Add the conformance along with this constraint.
14031413
equivClass->conformsTo[proto].push_back({this, proto, source});
14041414
++NumConformanceConstraints;
@@ -1866,6 +1876,12 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
18661876
if (!assocType && !concreteDecl)
18671877
return nullptr;
18681878

1879+
// If we were asked for a complete, well-formed archetype, make sure we
1880+
// process delayed requirements if anything changed.
1881+
SWIFT_DEFER {
1882+
getBuilder()->processDelayedRequirements();
1883+
};
1884+
18691885
Identifier name = assocType ? assocType->getName() : concreteDecl->getName();
18701886
ProtocolDecl *proto =
18711887
assocType ? assocType->getProtocol()
@@ -1900,6 +1916,9 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
19001916
switch (kind) {
19011917
case ArchetypeResolutionKind::CompleteWellFormed:
19021918
case ArchetypeResolutionKind::WellFormed: {
1919+
// Bump the generation count, because we created a new archetype.
1920+
++getBuilder()->Impl->Generation;
1921+
19031922
if (assocType)
19041923
resultPA = new PotentialArchetype(this, assocType);
19051924
else
@@ -2818,6 +2837,9 @@ ConstraintResult GenericSignatureBuilder::addLayoutRequirement(
28182837
return ConstraintResult::Resolved;
28192838
}
28202839

2840+
// Bump the generation.
2841+
++Impl->Generation;
2842+
28212843
auto pa = resolvedSubject->getPotentialArchetype();
28222844
return addLayoutRequirementDirect(pa, layout, source.getSource(pa));
28232845
}
@@ -2902,6 +2924,9 @@ ConstraintResult GenericSignatureBuilder::addSuperclassRequirementDirect(
29022924
.push_back(ConcreteConstraint{T, superclass, source});
29032925
++NumSuperclassConstraints;
29042926

2927+
// Bump the generation.
2928+
++Impl->Generation;
2929+
29052930
// Update the equivalence class with the constraint.
29062931
updateSuperclass(T, superclass, source);
29072932
return ConstraintResult::Resolved;
@@ -3061,6 +3086,9 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
30613086
if (T1 == T2)
30623087
return ConstraintResult::Resolved;
30633088

3089+
// Bump the generation.
3090+
++Impl->Generation;
3091+
30643092
unsigned nestingDepth1 = T1->getNestingDepth();
30653093
unsigned nestingDepth2 = T2->getNestingDepth();
30663094

@@ -3196,6 +3224,9 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirementToConcrete(
31963224
ConcreteConstraint{T, Concrete, Source});
31973225
++NumConcreteTypeConstraints;
31983226

3227+
// Bump the generation.
3228+
++Impl->Generation;
3229+
31993230
// If we've already been bound to a type, match that type.
32003231
if (equivClass->concreteType) {
32013232
return addSameTypeRequirement(equivClass->concreteType, Concrete, Source,
@@ -3978,6 +4009,13 @@ static GenericSignatureBuilder::UnresolvedType asUnresolvedType(
39784009
}
39794010

39804011
void GenericSignatureBuilder::processDelayedRequirements() {
4012+
// If we're already up-to-date, do nothing.
4013+
if (Impl->Generation == Impl->LastProcessedGeneration) return;
4014+
4015+
SWIFT_DEFER {
4016+
Impl->LastProcessedGeneration = Impl->Generation;
4017+
};
4018+
39814019
bool anySolved = !Impl->DelayedRequirements.empty();
39824020
while (anySolved) {
39834021
// Steal the delayed requirements so we can reprocess them.

test/decl/protocol/recursive_requirement_ok.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ protocol P {
99
func testP<T: P>(_ t: T) {
1010
testP(t.assoc)
1111
testP(t.assoc.assoc)
12-
testP(t.assoc.assoc.assoc) // FIXME: expected-error{{argument type 'T.Assoc.Assoc.Assoc' does not conform to expected type 'P'}}
12+
testP(t.assoc.assoc.assoc)
13+
testP(t.assoc.assoc.assoc.assoc.assoc.assoc.assoc)
1314
}

0 commit comments

Comments
 (0)