@@ -42,10 +42,11 @@ using namespace rewriting;
4242// / concrete type requirements.
4343static bool shouldSplitConcreteEquivalenceClass (
4444 Requirement req,
45+ const ProtocolDecl *proto,
4546 const RequirementMachine *machine) {
4647 return (req.getKind () == RequirementKind::SameType &&
4748 req.getSecondType ()->isTypeParameter () &&
48- machine->isConcreteType (req.getSecondType ()));
49+ machine->isConcreteType (req.getSecondType (), proto ));
4950}
5051
5152// / Returns true if this generic signature contains abstract same-type
@@ -54,9 +55,24 @@ static bool shouldSplitConcreteEquivalenceClass(
5455// / requirements, and minimize the signature again.
5556static bool shouldSplitConcreteEquivalenceClasses (
5657 ArrayRef<Requirement> requirements,
58+ const ProtocolDecl *proto,
5759 const RequirementMachine *machine) {
5860 for (auto req : requirements) {
59- if (shouldSplitConcreteEquivalenceClass (req, machine))
61+ if (shouldSplitConcreteEquivalenceClass (req, proto, machine))
62+ return true ;
63+ }
64+
65+ return false ;
66+ }
67+
68+ // / Same as the above, but with the requirements of a protocol connected
69+ // / component.
70+ static bool shouldSplitConcreteEquivalenceClasses (
71+ const llvm::DenseMap<const ProtocolDecl *, RequirementSignature> &protos,
72+ const RequirementMachine *machine) {
73+ for (const auto &pair : protos) {
74+ if (shouldSplitConcreteEquivalenceClasses (pair.second .getRequirements (),
75+ pair.first , machine))
6076 return true ;
6177 }
6278
@@ -71,14 +87,14 @@ static bool shouldSplitConcreteEquivalenceClasses(
7187static void splitConcreteEquivalenceClasses (
7288 ASTContext &ctx,
7389 ArrayRef<Requirement> requirements,
90+ const ProtocolDecl *proto,
7491 const RequirementMachine *machine,
7592 TypeArrayView<GenericTypeParamType> genericParams,
7693 SmallVectorImpl<StructuralRequirement> &splitRequirements,
7794 unsigned &attempt) {
7895 unsigned maxAttempts =
7996 ctx.LangOpts .RequirementMachineMaxSplitConcreteEquivClassAttempts ;
8097
81- ++attempt;
8298 if (attempt >= maxAttempts) {
8399 llvm::errs () << " Splitting concrete equivalence classes did not "
84100 << " reach fixed point after " << attempt << " attempts.\n " ;
@@ -94,9 +110,9 @@ static void splitConcreteEquivalenceClasses(
94110 splitRequirements.clear ();
95111
96112 for (auto req : requirements) {
97- if (shouldSplitConcreteEquivalenceClass (req, machine)) {
113+ if (shouldSplitConcreteEquivalenceClass (req, proto, machine)) {
98114 auto concreteType = machine->getConcreteType (
99- req.getSecondType (), genericParams);
115+ req.getSecondType (), genericParams, proto );
100116
101117 Requirement firstReq (RequirementKind::SameType,
102118 req.getFirstType (), concreteType);
@@ -111,6 +127,25 @@ static void splitConcreteEquivalenceClasses(
111127 }
112128}
113129
130+ // / Same as the above, but with the requirements of a protocol connected
131+ // / component.
132+ static void splitConcreteEquivalenceClasses (
133+ ASTContext &ctx,
134+ const llvm::DenseMap<const ProtocolDecl *, RequirementSignature> &protos,
135+ const RequirementMachine *machine,
136+ llvm::DenseMap<const ProtocolDecl *,
137+ SmallVector<StructuralRequirement, 4 >> &splitProtos,
138+ unsigned &attempt) {
139+ for (const auto &pair : protos) {
140+ const auto *proto = pair.first ;
141+ auto genericParams = proto->getGenericSignature ().getGenericParams ();
142+ splitConcreteEquivalenceClasses (ctx, pair.second .getRequirements (),
143+ proto, machine, genericParams,
144+ splitProtos[proto],
145+ attempt);
146+ }
147+ }
148+
114149// / Builds the requirement signatures for each protocol in this strongly
115150// / connected component.
116151llvm::DenseMap<const ProtocolDecl *, RequirementSignature>
@@ -195,87 +230,99 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
195230 requirements.push_back ({req, SourceLoc (), /* inferred=*/ false });
196231 }
197232
198- // Heap-allocate the requirement machine to save stack space.
199- std::unique_ptr<RequirementMachine> machine (new RequirementMachine (
200- ctx.getRewriteContext ()));
233+ unsigned attempt = 0 ;
234+ for (;;) {
235+ // Heap-allocate the requirement machine to save stack space.
236+ std::unique_ptr<RequirementMachine> machine (new RequirementMachine (
237+ ctx.getRewriteContext ()));
201238
202- auto status = machine->initWithProtocolWrittenRequirements (component, protos);
203- if (status.first != CompletionResult::Success) {
204- // All we can do at this point is diagnose and give each protocol an empty
205- // requirement signature.
206- for (const auto *otherProto : component) {
207- ctx.Diags .diagnose (otherProto->getLoc (),
208- diag::requirement_machine_completion_failed,
209- /* protocol=*/ 1 ,
210- unsigned (status.first ));
239+ auto status = machine->initWithProtocolWrittenRequirements (component, protos);
240+ if (status.first != CompletionResult::Success) {
241+ // All we can do at this point is diagnose and give each protocol an empty
242+ // requirement signature.
243+ for (const auto *otherProto : component) {
244+ ctx.Diags .diagnose (otherProto->getLoc (),
245+ diag::requirement_machine_completion_failed,
246+ /* protocol=*/ 1 ,
247+ unsigned (status.first ));
248+
249+ auto rule = machine->getRuleAsStringForDiagnostics (status.second );
250+ ctx.Diags .diagnose (otherProto->getLoc (),
251+ diag::requirement_machine_completion_rule,
252+ rule);
253+
254+ if (otherProto != proto) {
255+ ctx.evaluator .cacheOutput (
256+ RequirementSignatureRequestRQM{const_cast <ProtocolDecl *>(otherProto)},
257+ RequirementSignature (GenericSignatureErrorFlags::CompletionFailed));
258+ }
259+ }
211260
212- auto rule = machine->getRuleAsStringForDiagnostics (status.second );
213- ctx.Diags .diagnose (otherProto->getLoc (),
214- diag::requirement_machine_completion_rule,
215- rule);
261+ return RequirementSignature (GenericSignatureErrorFlags::CompletionFailed);
262+ }
216263
217- if (otherProto != proto) {
218- ctx.evaluator .cacheOutput (
219- RequirementSignatureRequestRQM{const_cast <ProtocolDecl *>(otherProto)},
220- RequirementSignature (GenericSignatureErrorFlags::CompletionFailed));
264+ auto minimalRequirements = machine->computeMinimalProtocolRequirements ();
265+
266+ if (!machine->getErrors ()) {
267+ if (shouldSplitConcreteEquivalenceClasses (minimalRequirements, machine.get ())) {
268+ ++attempt;
269+ splitConcreteEquivalenceClasses (ctx, minimalRequirements,
270+ machine.get (), protos, attempt);
271+ continue ;
221272 }
222273 }
223274
224- return RequirementSignature (GenericSignatureErrorFlags::CompletionFailed);
225- }
226-
227- auto minimalRequirements = machine->computeMinimalProtocolRequirements ();
275+ bool debug = machine->getDebugOptions ().contains (DebugFlags::Minimization);
228276
229- bool debug = machine->getDebugOptions ().contains (DebugFlags::Minimization);
277+ // The requirement signature for the actual protocol that the result
278+ // was kicked off with.
279+ Optional<RequirementSignature> result;
230280
231- // The requirement signature for the actual protocol that the result
232- // was kicked off with.
233- Optional<RequirementSignature> result;
281+ if (debug) {
282+ llvm::dbgs () << " \n Requirement signatures: \n " ;
283+ }
234284
235- if (debug ) {
236- llvm::dbgs () << " \n Requirement signatures: \n " ;
237- }
285+ for ( const auto &pair : minimalRequirements ) {
286+ auto *otherProto = pair. first ;
287+ const auto &reqs = pair. second ;
238288
239- for ( const auto &pair : minimalRequirements) {
240- auto *otherProto = pair. first ;
241- const auto &reqs = pair. second ;
289+ // Dump the result if requested.
290+ if (debug) {
291+ llvm::dbgs () << " - Protocol " << otherProto-> getName () << " : " ;
242292
243- // Dump the result if requested.
244- if (debug) {
245- llvm::dbgs () << " - Protocol " << otherProto-> getName () << " : " ;
293+ auto sig = GenericSignature::get (
294+ otherProto-> getGenericSignature (). getGenericParams (),
295+ reqs. getRequirements ()) ;
246296
247- auto sig = GenericSignature::get (
248- otherProto->getGenericSignature ().getGenericParams (),
249- reqs.getRequirements ());
297+ PrintOptions opts;
298+ opts.ProtocolQualifiedDependentMemberTypes = true ;
299+ sig.print (llvm::dbgs (), opts);
300+ llvm::dbgs () << " \n " ;
301+ }
250302
251- PrintOptions opts;
252- opts.ProtocolQualifiedDependentMemberTypes = true ;
253- sig.print (llvm::dbgs (), opts);
254- llvm::dbgs () << " \n " ;
303+ // Don't call setRequirementSignature() on the original proto; the
304+ // request evaluator will do it for us.
305+ if (otherProto == proto)
306+ result = reqs;
307+ else {
308+ auto temp = reqs;
309+ ctx.evaluator .cacheOutput (
310+ RequirementSignatureRequestRQM{const_cast <ProtocolDecl *>(otherProto)},
311+ std::move (temp));
312+ }
255313 }
256314
257- // Don't call setRequirementSignature() on the original proto; the
258- // request evaluator will do it for us.
259- if (otherProto == proto)
260- result = reqs;
261- else {
262- auto temp = reqs;
263- ctx.evaluator .cacheOutput (
264- RequirementSignatureRequestRQM{const_cast <ProtocolDecl *>(otherProto)},
265- std::move (temp));
315+ if (ctx.LangOpts .RequirementMachineProtocolSignatures ==
316+ RequirementMachineMode::Enabled) {
317+ SmallVector<RequirementError, 4 > errors;
318+ machine->System .computeRedundantRequirementDiagnostics (errors);
319+ diagnoseRequirementErrors (ctx, errors,
320+ /* allowConcreteGenericParams=*/ false );
266321 }
267- }
268322
269- if (ctx.LangOpts .RequirementMachineProtocolSignatures ==
270- RequirementMachineMode::Enabled) {
271- SmallVector<RequirementError, 4 > errors;
272- machine->System .computeRedundantRequirementDiagnostics (errors);
273- diagnoseRequirementErrors (ctx, errors,
274- /* allowConcreteGenericParams=*/ false );
323+ // Return the result for the specific protocol this request was kicked off on.
324+ return *result;
275325 }
276-
277- // Return the result for the specific protocol this request was kicked off on.
278- return *result;
279326}
280327
281328// / Builds the top-level generic signature requirements for this rewrite system.
@@ -479,9 +526,12 @@ AbstractGenericSignatureRequestRQM::evaluate(
479526
480527 if (!errorFlags) {
481528 if (shouldSplitConcreteEquivalenceClasses (result.getRequirements (),
529+ /* proto=*/ nullptr ,
482530 machine.get ())) {
531+ ++attempt;
483532 splitConcreteEquivalenceClasses (ctx, result.getRequirements (),
484- machine.get (), result.getGenericParams (),
533+ /* proto=*/ nullptr , machine.get (),
534+ result.getGenericParams (),
485535 requirements, attempt);
486536 continue ;
487537 }
@@ -646,9 +696,12 @@ InferredGenericSignatureRequestRQM::evaluate(
646696 if (!errorFlags) {
647697 // Check if we need to rebuild the signature.
648698 if (shouldSplitConcreteEquivalenceClasses (result.getRequirements (),
699+ /* proto=*/ nullptr ,
649700 machine.get ())) {
701+ ++attempt;
650702 splitConcreteEquivalenceClasses (ctx, result.getRequirements (),
651- machine.get (), result.getGenericParams (),
703+ /* proto=*/ nullptr , machine.get (),
704+ result.getGenericParams (),
652705 requirements, attempt);
653706 continue ;
654707 }
0 commit comments