@@ -7438,32 +7438,58 @@ GenericSignature *GenericSignatureBuilder::computeRequirementSignature(
7438
7438
7439
7439
#pragma mark Generic signature verification
7440
7440
7441
- void GenericSignatureBuilder::verifyGenericSignature (ASTContext &context,
7442
- GenericSignature *sig) {
7443
- llvm::errs () << " Validating generic signature: " ;
7444
- sig->print (llvm::errs ());
7445
- llvm::errs () << " \n " ;
7441
+ void GenericSignatureBuilder::dropAndCompareEachRequirement (
7442
+ ASTContext &context, GenericSignature *baseSig, GenericSignature *sig,
7443
+ bool includeRedundantRequirements, SmallVectorImpl<Requirement> &redundant,
7444
+ SmallVectorImpl<Requirement> &nonRedundant) {
7445
+ #ifndef NDEBUG
7446
+ // `baseSig`'s params should be a subset of `sig`, meaning <A where ...>, <A,
7447
+ // B where ...> (respectively) is okay, but the reverse is not.
7448
+ if (baseSig) {
7449
+ auto canSigParams = sig->getCanonicalSignature ()->getGenericParams ();
7450
+ for (auto baseParam :
7451
+ baseSig->getCanonicalSignature ()->getGenericParams ()) {
7452
+ assert (llvm::is_contained (canSigParams, baseParam) &&
7453
+ " baseSig params aren't a subset of sig" );
7454
+ }
7455
+ }
7456
+ #endif
7446
7457
7447
- // Try removing each requirement in turn.
7448
7458
auto genericParams = sig->getGenericParams ();
7449
7459
auto requirements = sig->getRequirements ();
7450
7460
for (unsigned victimIndex : indices (requirements)) {
7451
- PrettyStackTraceGenericSignature debugStack (" verifying" , sig, victimIndex);
7461
+ PrettyStackTraceGenericSignature debugStack (" dropping & comparing" , sig,
7462
+ victimIndex);
7452
7463
7453
7464
// Form a new generic signature builder.
7454
7465
GenericSignatureBuilder builder (context);
7455
7466
7456
- // Add the generic parameters.
7467
+ // Add the generic parameters, and specifically those from the main
7468
+ // signature, since it may have more
7457
7469
for (auto gp : genericParams)
7458
7470
builder.addGenericParameter (gp);
7459
7471
7460
- // Add the requirements *except* the victim.
7472
+ // Add the appropriate requirements
7461
7473
auto source = FloatingRequirementSource::forAbstract ();
7462
- for (unsigned i : indices (requirements)) {
7463
- if (i != victimIndex)
7464
- builder.addRequirement (requirements[i], source, nullptr );
7474
+ // First, the universal requirements from the base
7475
+ if (baseSig) {
7476
+ for (auto req : baseSig->getRequirements ())
7477
+ builder.addRequirement (req, source, nullptr );
7465
7478
}
7466
7479
7480
+ // Next, the requirements from the interesting signature. Sometimes we have
7481
+ // to add all of the leading ones, and others times only those that we've
7482
+ // already decided aren't redundant:
7483
+ auto leadingReqs = includeRedundantRequirements
7484
+ ? requirements.slice (0 , victimIndex)
7485
+ : nonRedundant;
7486
+ // We definitely have to add all of the remaining trailing ones:
7487
+ auto trailingReqs = requirements.slice (victimIndex + 1 );
7488
+
7489
+ for (auto reqs : {leadingReqs, trailingReqs})
7490
+ for (auto req : reqs)
7491
+ builder.addRequirement (req, source, nullptr );
7492
+
7467
7493
// Finalize the generic signature. If there were any errors, we formed
7468
7494
// an invalid signature, so just continue.
7469
7495
if (builder.Impl ->HadAnyError ) continue ;
@@ -7475,23 +7501,40 @@ void GenericSignatureBuilder::verifyGenericSignature(ASTContext &context,
7475
7501
/* allowConcreteGenericParams=*/ true ,
7476
7502
/* allowBuilderToMove=*/ true );
7477
7503
7478
- // If the removed requirement is satisfied by the new generic signature,
7479
- // it is redundant. Complain.
7480
- if (newSig->isRequirementSatisfied (requirements[victimIndex])) {
7481
- SmallString<32 > reqString;
7482
- {
7483
- llvm::raw_svector_ostream out (reqString);
7484
- requirements[victimIndex].print (out, PrintOptions ());
7485
- }
7486
- context.Diags .diagnose (SourceLoc (), diag::generic_signature_not_minimal,
7487
- reqString, sig->getAsString ());
7488
- }
7504
+ auto req = requirements[victimIndex];
7505
+ if (newSig->isRequirementSatisfied (req))
7506
+ redundant.push_back (req);
7507
+ else
7508
+ nonRedundant.push_back (req);
7489
7509
7490
7510
// Canonicalize the signature to check that it is canonical.
7491
7511
(void )newSig->getCanonicalSignature ();
7492
7512
}
7493
7513
}
7494
7514
7515
+ void GenericSignatureBuilder::verifyGenericSignature (ASTContext &context,
7516
+ GenericSignature *sig) {
7517
+ llvm::errs () << " Validating generic signature: " ;
7518
+ sig->print (llvm::errs ());
7519
+ llvm::errs () << " \n " ;
7520
+
7521
+ SmallVector<Requirement, 4 > redundant;
7522
+ SmallVector<Requirement, 4 > _nonRedundant;
7523
+ dropAndCompareEachRequirement (context, /* baseSig=*/ nullptr , sig,
7524
+ /* includeRedundantRequirements=*/ true ,
7525
+ redundant, _nonRedundant);
7526
+ for (auto req : redundant) {
7527
+ // Oops, the signature wasn't minimal: complain.
7528
+ SmallString<32 > reqString;
7529
+ {
7530
+ llvm::raw_svector_ostream out (reqString);
7531
+ req.print (out, PrintOptions ());
7532
+ }
7533
+ context.Diags .diagnose (SourceLoc (), diag::generic_signature_not_minimal,
7534
+ reqString, sig->getAsString ());
7535
+ }
7536
+ }
7537
+
7495
7538
void GenericSignatureBuilder::verifyGenericSignaturesInModule (
7496
7539
ModuleDecl *module ) {
7497
7540
LoadedFile *loadedFile = nullptr ;
0 commit comments