@@ -254,6 +254,10 @@ static bool shouldSplitConcreteEquivalenceClass(Requirement req,
254
254
sig->isConcreteType (req.getSecondType ()));
255
255
}
256
256
257
+ // / Returns true if this generic signature contains abstract same-type
258
+ // / requirements between concrete type parameters. In this case, we split
259
+ // / the abstract same-type requirements into pairs of concrete type
260
+ // / requirements, and minimize the signature again.
257
261
static bool shouldSplitConcreteEquivalenceClasses (GenericSignature sig) {
258
262
for (auto req : sig.getRequirements ()) {
259
263
if (shouldSplitConcreteEquivalenceClass (req, sig))
@@ -263,37 +267,34 @@ static bool shouldSplitConcreteEquivalenceClasses(GenericSignature sig) {
263
267
return false ;
264
268
}
265
269
266
- static GenericSignature splitConcreteEquivalenceClasses (
267
- GenericSignature sig, ASTContext &ctx) {
268
- SmallVector<Requirement, 2 > reqs;
270
+ // / Replace each same-type requirement 'T == U' where 'T' (and therefore 'U')
271
+ // / is known to equal a concrete type 'C' with a pair of requirements
272
+ // / 'T == C' and 'U == C'. We build the signature again in this case, since
273
+ // / one of the two requirements will be redundant, but we don't know which
274
+ // / ahead of time.
275
+ static void splitConcreteEquivalenceClasses (
276
+ ASTContext &ctx,
277
+ GenericSignature sig,
278
+ SmallVectorImpl<StructuralRequirement> &requirements) {
279
+ requirements.clear ();
269
280
270
281
for (auto req : sig.getRequirements ()) {
271
282
if (shouldSplitConcreteEquivalenceClass (req, sig)) {
272
283
auto canType = sig->getSugaredType (
273
284
sig.getCanonicalTypeInContext (
274
285
req.getSecondType ()));
275
286
276
- reqs.emplace_back (RequirementKind::SameType,
277
- req.getFirstType (),
278
- canType);
279
- reqs.emplace_back (RequirementKind::SameType,
280
- req.getSecondType (),
281
- canType);
282
- } else {
283
- reqs.push_back (req);
287
+ Requirement firstReq (RequirementKind::SameType,
288
+ req.getFirstType (), canType);
289
+ Requirement secondReq (RequirementKind::SameType,
290
+ req.getSecondType (), canType);
291
+ requirements.push_back ({firstReq, SourceLoc (), /* inferred=*/ false });
292
+ requirements.push_back ({secondReq, SourceLoc (), /* inferred=*/ false });
293
+ continue ;
284
294
}
285
- }
286
-
287
- SmallVector<GenericTypeParamType *, 2 > genericParams;
288
- genericParams.append (sig.getGenericParams ().begin (),
289
- sig.getGenericParams ().end ());
290
295
291
- return evaluateOrDefault (
292
- ctx.evaluator ,
293
- AbstractGenericSignatureRequestRQM{
294
- /* baseSignature=*/ nullptr ,
295
- genericParams, reqs},
296
- GenericSignatureWithError ()).getPointer ();
296
+ requirements.push_back ({req, SourceLoc (), /* inferred=*/ false });
297
+ }
297
298
}
298
299
299
300
GenericSignatureWithError
@@ -427,32 +428,36 @@ AbstractGenericSignatureRequestRQM::evaluate(
427
428
}
428
429
}
429
430
430
- // Heap-allocate the requirement machine to save stack space.
431
- std::unique_ptr<RequirementMachine> machine (new RequirementMachine (
432
- ctx.getRewriteContext ()));
431
+ for (;;) {
432
+ // Heap-allocate the requirement machine to save stack space.
433
+ std::unique_ptr<RequirementMachine> machine (new RequirementMachine (
434
+ ctx.getRewriteContext ()));
433
435
434
- auto status =
435
- machine->initWithWrittenRequirements (genericParams, requirements);
436
- machine->checkCompletionResult (status.first );
436
+ auto status =
437
+ machine->initWithWrittenRequirements (genericParams, requirements);
438
+ machine->checkCompletionResult (status.first );
437
439
438
- // We pass reconstituteSugar=false to ensure that if the original
439
- // requirements were canonical, the final signature remains canonical.
440
- auto minimalRequirements =
441
- machine->computeMinimalGenericSignatureRequirements (
442
- /* reconstituteSugar=*/ false );
440
+ // We pass reconstituteSugar=false to ensure that if the original
441
+ // requirements were canonical, the final signature remains canonical.
442
+ auto minimalRequirements =
443
+ machine->computeMinimalGenericSignatureRequirements (
444
+ /* reconstituteSugar=*/ false );
443
445
444
- auto result = GenericSignature::get (genericParams, minimalRequirements);
445
- auto errorFlags = machine->getErrors ();
446
+ auto result = GenericSignature::get (genericParams, minimalRequirements);
447
+ auto errorFlags = machine->getErrors ();
446
448
447
- if (!errorFlags) {
448
- if (shouldSplitConcreteEquivalenceClasses (result))
449
- result = splitConcreteEquivalenceClasses (result, ctx);
449
+ if (!errorFlags) {
450
+ if (shouldSplitConcreteEquivalenceClasses (result)) {
451
+ splitConcreteEquivalenceClasses (ctx, result, requirements);
452
+ continue ;
453
+ }
450
454
451
- // Check invariants.
452
- result.verify ();
453
- }
455
+ // Check invariants.
456
+ result.verify ();
457
+ }
454
458
455
- return GenericSignatureWithError (result, errorFlags);
459
+ return GenericSignatureWithError (result, errorFlags);
460
+ }
456
461
}
457
462
458
463
GenericSignatureWithError
@@ -563,51 +568,55 @@ InferredGenericSignatureRequestRQM::evaluate(
563
568
}
564
569
}
565
570
566
- // Heap-allocate the requirement machine to save stack space.
567
- std::unique_ptr<RequirementMachine> machine (new RequirementMachine (
568
- ctx.getRewriteContext ()));
571
+ for (;;) {
572
+ // Heap-allocate the requirement machine to save stack space.
573
+ std::unique_ptr<RequirementMachine> machine (new RequirementMachine (
574
+ ctx.getRewriteContext ()));
569
575
570
- auto status =
571
- machine->initWithWrittenRequirements (genericParams, requirements);
572
- if (status.first != CompletionResult::Success) {
573
- ctx.Diags .diagnose (loc,
574
- diag::requirement_machine_completion_failed,
575
- /* protocol=*/ 0 ,
576
- unsigned (status.first ));
576
+ auto status =
577
+ machine->initWithWrittenRequirements (genericParams, requirements);
578
+ if (status.first != CompletionResult::Success) {
579
+ ctx.Diags .diagnose (loc,
580
+ diag::requirement_machine_completion_failed,
581
+ /* protocol=*/ 0 ,
582
+ unsigned (status.first ));
577
583
578
- auto rule = machine->getRuleAsStringForDiagnostics (status.second );
579
- ctx.Diags .diagnose (loc,
580
- diag::requirement_machine_completion_rule,
581
- rule);
584
+ auto rule = machine->getRuleAsStringForDiagnostics (status.second );
585
+ ctx.Diags .diagnose (loc,
586
+ diag::requirement_machine_completion_rule,
587
+ rule);
582
588
583
- auto result = GenericSignature::get (genericParams,
584
- parentSig.getRequirements ());
585
- return GenericSignatureWithError (
586
- result, GenericSignatureErrorFlags::CompletionFailed);
587
- }
589
+ auto result = GenericSignature::get (genericParams,
590
+ parentSig.getRequirements ());
591
+ return GenericSignatureWithError (
592
+ result, GenericSignatureErrorFlags::CompletionFailed);
593
+ }
588
594
589
- auto minimalRequirements =
590
- machine->computeMinimalGenericSignatureRequirements (
591
- /* reconstituteSugar=*/ true );
595
+ auto minimalRequirements =
596
+ machine->computeMinimalGenericSignatureRequirements (
597
+ /* reconstituteSugar=*/ true );
592
598
593
- auto result = GenericSignature::get (genericParams, minimalRequirements);
594
- auto errorFlags = machine->getErrors ();
599
+ auto result = GenericSignature::get (genericParams, minimalRequirements);
600
+ auto errorFlags = machine->getErrors ();
595
601
596
- if (ctx.LangOpts .RequirementMachineInferredSignatures ==
597
- RequirementMachineMode::Enabled) {
598
- machine->System .computeRedundantRequirementDiagnostics (errors);
599
- diagnoseRequirementErrors (ctx, errors, allowConcreteGenericParams);
600
- }
602
+ if (ctx.LangOpts .RequirementMachineInferredSignatures ==
603
+ RequirementMachineMode::Enabled) {
604
+ machine->System .computeRedundantRequirementDiagnostics (errors);
605
+ diagnoseRequirementErrors (ctx, errors, allowConcreteGenericParams);
606
+ }
601
607
602
- // FIXME: Handle allowConcreteGenericParams
608
+ // FIXME: Handle allowConcreteGenericParams
603
609
604
- if (!errorFlags) {
605
- if (shouldSplitConcreteEquivalenceClasses (result))
606
- result = splitConcreteEquivalenceClasses (result, ctx);
610
+ if (!errorFlags) {
611
+ if (shouldSplitConcreteEquivalenceClasses (result)) {
612
+ splitConcreteEquivalenceClasses (ctx, result, requirements);
613
+ continue ;
614
+ }
607
615
608
- // Check invariants.
609
- result.verify ();
610
- }
616
+ // Check invariants.
617
+ result.verify ();
618
+ }
611
619
612
- return GenericSignatureWithError (result, errorFlags);
620
+ return GenericSignatureWithError (result, errorFlags);
621
+ }
613
622
}
0 commit comments