36
36
#include " llvm/ADT/Statistic.h"
37
37
#include " llvm/ADT/STLExtras.h"
38
38
#include " llvm/Support/raw_ostream.h"
39
+ #include " llvm/Support/SaveAndRestore.h"
39
40
#include < algorithm>
40
41
41
42
using namespace swift ;
@@ -72,6 +73,16 @@ STATISTIC(NumArchetypeAnchorCacheHits,
72
73
" # of hits in the archetype anchor cache" );
73
74
STATISTIC (NumArchetypeAnchorCacheMisses,
74
75
" # of misses in the archetype anchor cache" );
76
+ STATISTIC (NumProcessDelayedRequirements,
77
+ " # of times we process delayed requirements" );
78
+ STATISTIC (NumProcessDelayedRequirementsUnchanged,
79
+ " # of times we process delayed requirements without change" );
80
+ STATISTIC (NumDelayedRequirementConcrete,
81
+ " Delayed requirements resolved as concrete" );
82
+ STATISTIC (NumDelayedRequirementResolved,
83
+ " Delayed requirements resolved" );
84
+ STATISTIC (NumDelayedRequirementUnresolved,
85
+ " Delayed requirements left unresolved" );
75
86
76
87
struct GenericSignatureBuilder ::Implementation {
77
88
// / Function used to look up conformances.
@@ -90,6 +101,16 @@ struct GenericSignatureBuilder::Implementation {
90
101
// / The set of requirements that have been delayed for some reason.
91
102
SmallVector<DelayedRequirement, 4 > DelayedRequirements;
92
103
104
+ // / The generation number, which is incremented whenever we successfully
105
+ // / introduce a new constraint.
106
+ unsigned Generation = 0 ;
107
+
108
+ // / The generation at which we last processed all of the delayed requirements.
109
+ unsigned LastProcessedGeneration = 0 ;
110
+
111
+ // / Whether we are currently processing delayed requirements.
112
+ bool ProcessingDelayedRequirements = false ;
113
+
93
114
#ifndef NDEBUG
94
115
// / Whether we've already finalized the builder.
95
116
bool finalized = false ;
@@ -1399,6 +1420,8 @@ bool PotentialArchetype::addConformance(ProtocolDecl *proto,
1399
1420
return false ;
1400
1421
}
1401
1422
1423
+ builder.bumpGeneration ();
1424
+
1402
1425
// Add the conformance along with this constraint.
1403
1426
equivClass->conformsTo [proto].push_back ({this , proto, source});
1404
1427
++NumConformanceConstraints;
@@ -1867,6 +1890,15 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
1867
1890
if (!assocType && !concreteDecl)
1868
1891
return nullptr ;
1869
1892
1893
+ // If we were asked for a complete, well-formed archetype, make sure we
1894
+ // process delayed requirements if anything changed.
1895
+ SWIFT_DEFER {
1896
+ ASTContext &ctx = assocType ? assocType->getASTContext ()
1897
+ : concreteDecl->getASTContext ();
1898
+ if (ctx.LangOpts .EnableRecursiveConstraints )
1899
+ getBuilder ()->processDelayedRequirements ();
1900
+ };
1901
+
1870
1902
Identifier name = assocType ? assocType->getName () : concreteDecl->getName ();
1871
1903
ProtocolDecl *proto =
1872
1904
assocType ? assocType->getProtocol ()
@@ -1901,6 +1933,8 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
1901
1933
switch (kind) {
1902
1934
case ArchetypeResolutionKind::CompleteWellFormed:
1903
1935
case ArchetypeResolutionKind::WellFormed: {
1936
+ builder.bumpGeneration ();
1937
+
1904
1938
if (assocType)
1905
1939
resultPA = new PotentialArchetype (this , assocType);
1906
1940
else
@@ -2819,6 +2853,8 @@ ConstraintResult GenericSignatureBuilder::addLayoutRequirement(
2819
2853
return ConstraintResult::Resolved;
2820
2854
}
2821
2855
2856
+ bumpGeneration ();
2857
+
2822
2858
auto pa = resolvedSubject->getPotentialArchetype ();
2823
2859
return addLayoutRequirementDirect (pa, layout, source.getSource (pa));
2824
2860
}
@@ -2903,6 +2939,8 @@ ConstraintResult GenericSignatureBuilder::addSuperclassRequirementDirect(
2903
2939
.push_back (ConcreteConstraint{T, superclass, source});
2904
2940
++NumSuperclassConstraints;
2905
2941
2942
+ bumpGeneration ();
2943
+
2906
2944
// Update the equivalence class with the constraint.
2907
2945
updateSuperclass (T, superclass, source);
2908
2946
return ConstraintResult::Resolved;
@@ -3062,6 +3100,8 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
3062
3100
if (T1 == T2)
3063
3101
return ConstraintResult::Resolved;
3064
3102
3103
+ bumpGeneration ();
3104
+
3065
3105
unsigned nestingDepth1 = T1->getNestingDepth ();
3066
3106
unsigned nestingDepth2 = T2->getNestingDepth ();
3067
3107
@@ -3197,6 +3237,8 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirementToConcrete(
3197
3237
ConcreteConstraint{T, Concrete, Source});
3198
3238
++NumConcreteTypeConstraints;
3199
3239
3240
+ bumpGeneration ();
3241
+
3200
3242
// If we've already been bound to a type, match that type.
3201
3243
if (equivClass->concreteType ) {
3202
3244
return addSameTypeRequirement (equivClass->concreteType , Concrete, Source,
@@ -3979,8 +4021,27 @@ static GenericSignatureBuilder::UnresolvedType asUnresolvedType(
3979
4021
}
3980
4022
3981
4023
void GenericSignatureBuilder::processDelayedRequirements () {
3982
- bool anySolved = !Impl->DelayedRequirements .empty ();
3983
- while (anySolved) {
4024
+ // If we're already up-to-date, do nothing.
4025
+ if (Impl->Generation == Impl->LastProcessedGeneration ) { return ; }
4026
+
4027
+ // If there are no delayed requirements, do nothing.
4028
+ if (Impl->DelayedRequirements .empty ()) { return ; }
4029
+
4030
+ if (Impl->ProcessingDelayedRequirements ) { return ; }
4031
+
4032
+ ++NumProcessDelayedRequirements;
4033
+
4034
+ llvm::SaveAndRestore<bool > processing (Impl->ProcessingDelayedRequirements ,
4035
+ true );
4036
+ bool anyChanges = false ;
4037
+ SWIFT_DEFER {
4038
+ Impl->LastProcessedGeneration = Impl->Generation ;
4039
+ if (!anyChanges)
4040
+ ++NumProcessDelayedRequirementsUnchanged;
4041
+ };
4042
+
4043
+ bool anySolved;
4044
+ do {
3984
4045
// Steal the delayed requirements so we can reprocess them.
3985
4046
anySolved = false ;
3986
4047
auto delayed = std::move (Impl->DelayedRequirements );
@@ -4013,21 +4074,35 @@ void GenericSignatureBuilder::processDelayedRequirements() {
4013
4074
// Update our state based on what happened.
4014
4075
switch (reqResult) {
4015
4076
case ConstraintResult::Concrete:
4077
+ ++NumDelayedRequirementConcrete;
4078
+ anySolved = true ;
4079
+ break ;
4080
+
4016
4081
case ConstraintResult::Conflicting:
4017
4082
anySolved = true ;
4018
4083
break ;
4019
4084
4020
4085
case ConstraintResult::Resolved:
4086
+ ++NumDelayedRequirementResolved;
4021
4087
anySolved = true ;
4022
4088
break ;
4023
4089
4024
4090
case ConstraintResult::Unresolved:
4025
4091
// Add the requirement back.
4092
+ ++NumDelayedRequirementUnresolved;
4026
4093
Impl->DelayedRequirements .push_back (req);
4027
4094
break ;
4028
4095
}
4029
4096
}
4030
- }
4097
+
4098
+ if (anySolved) {
4099
+ anyChanges = true ;
4100
+ }
4101
+ } while (anySolved);
4102
+ }
4103
+
4104
+ void GenericSignatureBuilder::bumpGeneration () {
4105
+ ++Impl->Generation ;
4031
4106
}
4032
4107
4033
4108
template <typename T>
0 commit comments