@@ -90,6 +90,13 @@ struct GenericSignatureBuilder::Implementation {
90
90
// / The set of requirements that have been delayed for some reason.
91
91
SmallVector<DelayedRequirement, 4 > DelayedRequirements;
92
92
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
+
93
100
#ifndef NDEBUG
94
101
// / Whether we've already finalized the builder.
95
102
bool finalized = false ;
@@ -1399,6 +1406,9 @@ bool PotentialArchetype::addConformance(ProtocolDecl *proto,
1399
1406
return false ;
1400
1407
}
1401
1408
1409
+ // Bump the generation.
1410
+ ++builder.Impl ->Generation ;
1411
+
1402
1412
// Add the conformance along with this constraint.
1403
1413
equivClass->conformsTo [proto].push_back ({this , proto, source});
1404
1414
++NumConformanceConstraints;
@@ -1866,6 +1876,12 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
1866
1876
if (!assocType && !concreteDecl)
1867
1877
return nullptr ;
1868
1878
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
+
1869
1885
Identifier name = assocType ? assocType->getName () : concreteDecl->getName ();
1870
1886
ProtocolDecl *proto =
1871
1887
assocType ? assocType->getProtocol ()
@@ -1900,6 +1916,9 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
1900
1916
switch (kind) {
1901
1917
case ArchetypeResolutionKind::CompleteWellFormed:
1902
1918
case ArchetypeResolutionKind::WellFormed: {
1919
+ // Bump the generation count, because we created a new archetype.
1920
+ ++getBuilder ()->Impl ->Generation ;
1921
+
1903
1922
if (assocType)
1904
1923
resultPA = new PotentialArchetype (this , assocType);
1905
1924
else
@@ -2818,6 +2837,9 @@ ConstraintResult GenericSignatureBuilder::addLayoutRequirement(
2818
2837
return ConstraintResult::Resolved;
2819
2838
}
2820
2839
2840
+ // Bump the generation.
2841
+ ++Impl->Generation ;
2842
+
2821
2843
auto pa = resolvedSubject->getPotentialArchetype ();
2822
2844
return addLayoutRequirementDirect (pa, layout, source.getSource (pa));
2823
2845
}
@@ -2902,6 +2924,9 @@ ConstraintResult GenericSignatureBuilder::addSuperclassRequirementDirect(
2902
2924
.push_back (ConcreteConstraint{T, superclass, source});
2903
2925
++NumSuperclassConstraints;
2904
2926
2927
+ // Bump the generation.
2928
+ ++Impl->Generation ;
2929
+
2905
2930
// Update the equivalence class with the constraint.
2906
2931
updateSuperclass (T, superclass, source);
2907
2932
return ConstraintResult::Resolved;
@@ -3061,6 +3086,9 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
3061
3086
if (T1 == T2)
3062
3087
return ConstraintResult::Resolved;
3063
3088
3089
+ // Bump the generation.
3090
+ ++Impl->Generation ;
3091
+
3064
3092
unsigned nestingDepth1 = T1->getNestingDepth ();
3065
3093
unsigned nestingDepth2 = T2->getNestingDepth ();
3066
3094
@@ -3196,6 +3224,9 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirementToConcrete(
3196
3224
ConcreteConstraint{T, Concrete, Source});
3197
3225
++NumConcreteTypeConstraints;
3198
3226
3227
+ // Bump the generation.
3228
+ ++Impl->Generation ;
3229
+
3199
3230
// If we've already been bound to a type, match that type.
3200
3231
if (equivClass->concreteType ) {
3201
3232
return addSameTypeRequirement (equivClass->concreteType , Concrete, Source,
@@ -3978,6 +4009,13 @@ static GenericSignatureBuilder::UnresolvedType asUnresolvedType(
3978
4009
}
3979
4010
3980
4011
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
+
3981
4019
bool anySolved = !Impl->DelayedRequirements .empty ();
3982
4020
while (anySolved) {
3983
4021
// Steal the delayed requirements so we can reprocess them.
0 commit comments