@@ -42,10 +42,11 @@ using namespace rewriting;
42
42
// / concrete type requirements.
43
43
static bool shouldSplitConcreteEquivalenceClass (
44
44
Requirement req,
45
+ const ProtocolDecl *proto,
45
46
const RequirementMachine *machine) {
46
47
return (req.getKind () == RequirementKind::SameType &&
47
48
req.getSecondType ()->isTypeParameter () &&
48
- machine->isConcreteType (req.getSecondType ()));
49
+ machine->isConcreteType (req.getSecondType (), proto ));
49
50
}
50
51
51
52
// / Returns true if this generic signature contains abstract same-type
@@ -54,9 +55,24 @@ static bool shouldSplitConcreteEquivalenceClass(
54
55
// / requirements, and minimize the signature again.
55
56
static bool shouldSplitConcreteEquivalenceClasses (
56
57
ArrayRef<Requirement> requirements,
58
+ const ProtocolDecl *proto,
57
59
const RequirementMachine *machine) {
58
60
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))
60
76
return true ;
61
77
}
62
78
@@ -71,14 +87,14 @@ static bool shouldSplitConcreteEquivalenceClasses(
71
87
static void splitConcreteEquivalenceClasses (
72
88
ASTContext &ctx,
73
89
ArrayRef<Requirement> requirements,
90
+ const ProtocolDecl *proto,
74
91
const RequirementMachine *machine,
75
92
TypeArrayView<GenericTypeParamType> genericParams,
76
93
SmallVectorImpl<StructuralRequirement> &splitRequirements,
77
94
unsigned &attempt) {
78
95
unsigned maxAttempts =
79
96
ctx.LangOpts .RequirementMachineMaxSplitConcreteEquivClassAttempts ;
80
97
81
- ++attempt;
82
98
if (attempt >= maxAttempts) {
83
99
llvm::errs () << " Splitting concrete equivalence classes did not "
84
100
<< " reach fixed point after " << attempt << " attempts.\n " ;
@@ -94,9 +110,9 @@ static void splitConcreteEquivalenceClasses(
94
110
splitRequirements.clear ();
95
111
96
112
for (auto req : requirements) {
97
- if (shouldSplitConcreteEquivalenceClass (req, machine)) {
113
+ if (shouldSplitConcreteEquivalenceClass (req, proto, machine)) {
98
114
auto concreteType = machine->getConcreteType (
99
- req.getSecondType (), genericParams);
115
+ req.getSecondType (), genericParams, proto );
100
116
101
117
Requirement firstReq (RequirementKind::SameType,
102
118
req.getFirstType (), concreteType);
@@ -111,6 +127,25 @@ static void splitConcreteEquivalenceClasses(
111
127
}
112
128
}
113
129
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
+
114
149
// / Builds the requirement signatures for each protocol in this strongly
115
150
// / connected component.
116
151
llvm::DenseMap<const ProtocolDecl *, RequirementSignature>
@@ -195,87 +230,99 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
195
230
requirements.push_back ({req, SourceLoc (), /* inferred=*/ false });
196
231
}
197
232
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 ()));
201
238
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
+ }
211
260
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
+ }
216
263
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 ;
221
272
}
222
273
}
223
274
224
- return RequirementSignature (GenericSignatureErrorFlags::CompletionFailed);
225
- }
226
-
227
- auto minimalRequirements = machine->computeMinimalProtocolRequirements ();
275
+ bool debug = machine->getDebugOptions ().contains (DebugFlags::Minimization);
228
276
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;
230
280
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
+ }
234
284
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 ;
238
288
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 () << " : " ;
242
292
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 ()) ;
246
296
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
+ }
250
302
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
+ }
255
313
}
256
314
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 );
266
321
}
267
- }
268
322
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;
275
325
}
276
-
277
- // Return the result for the specific protocol this request was kicked off on.
278
- return *result;
279
326
}
280
327
281
328
// / Builds the top-level generic signature requirements for this rewrite system.
@@ -479,9 +526,12 @@ AbstractGenericSignatureRequestRQM::evaluate(
479
526
480
527
if (!errorFlags) {
481
528
if (shouldSplitConcreteEquivalenceClasses (result.getRequirements (),
529
+ /* proto=*/ nullptr ,
482
530
machine.get ())) {
531
+ ++attempt;
483
532
splitConcreteEquivalenceClasses (ctx, result.getRequirements (),
484
- machine.get (), result.getGenericParams (),
533
+ /* proto=*/ nullptr , machine.get (),
534
+ result.getGenericParams (),
485
535
requirements, attempt);
486
536
continue ;
487
537
}
@@ -646,9 +696,12 @@ InferredGenericSignatureRequestRQM::evaluate(
646
696
if (!errorFlags) {
647
697
// Check if we need to rebuild the signature.
648
698
if (shouldSplitConcreteEquivalenceClasses (result.getRequirements (),
699
+ /* proto=*/ nullptr ,
649
700
machine.get ())) {
701
+ ++attempt;
650
702
splitConcreteEquivalenceClasses (ctx, result.getRequirements (),
651
- machine.get (), result.getGenericParams (),
703
+ /* proto=*/ nullptr , machine.get (),
704
+ result.getGenericParams (),
652
705
requirements, attempt);
653
706
continue ;
654
707
}
0 commit comments