Skip to content

Commit b834168

Browse files
committed
AST: Fast path for matching can. signatures in requirementsNotSatisfiedBy
1 parent 52c3d70 commit b834168

File tree

2 files changed

+28
-33
lines changed

2 files changed

+28
-33
lines changed

lib/AST/GenericSignature.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -595,16 +595,20 @@ SmallVector<Requirement, 4> GenericSignatureImpl::requirementsNotSatisfiedBy(
595595
GenericSignature otherSig) {
596596
SmallVector<Requirement, 4> result;
597597

598-
// If the signatures are the same, all requirements are satisfied.
598+
// If the signatures match by pointer, all requirements are satisfied.
599599
if (otherSig.getPointer() == this) return result;
600600

601601
// If there is no other signature, no requirements are satisfied.
602602
if (!otherSig){
603-
result.insert(result.end(),
604-
getRequirements().begin(), getRequirements().end());
603+
const auto reqs = getRequirements();
604+
result.append(reqs.begin(), reqs.end());
605605
return result;
606606
}
607607

608+
// If the canonical signatures are equal, all requirements are satisfied.
609+
if (getCanonicalSignature() == otherSig->getCanonicalSignature())
610+
return result;
611+
608612
// Find the requirements that aren't satisfied.
609613
for (const auto &req : getRequirements()) {
610614
if (!otherSig->isRequirementSatisfied(req))

lib/AST/ProtocolConformance.cpp

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ void NormalProtocolConformance::differenceAndStoreConditionalRequirements()
501501
};
502502

503503
CRState = ConditionalRequirementsState::Computing;
504-
auto success = [this](ArrayRef<Requirement> reqs) {
504+
auto success = [this](ArrayRef<Requirement> reqs = {}) {
505505
ConditionalRequirements = reqs;
506506
assert(CRState == ConditionalRequirementsState::Computing);
507507
CRState = ConditionalRequirementsState::Complete;
@@ -510,30 +510,23 @@ void NormalProtocolConformance::differenceAndStoreConditionalRequirements()
510510
assert(CRState == ConditionalRequirementsState::Computing);
511511
CRState = ConditionalRequirementsState::Uncomputed;
512512
};
513-
514-
auto &ctxt = getProtocol()->getASTContext();
515-
auto DC = getDeclContext();
516-
// A non-extension conformance won't have conditional requirements.
517-
if (!isa<ExtensionDecl>(DC)) {
518-
success({});
519-
return;
520-
}
521513

522-
auto *ext = cast<ExtensionDecl>(DC);
523-
auto nominal = ext->getExtendedNominal();
524-
auto typeSig = nominal->getGenericSignature();
525-
526-
// A non-generic type won't have conditional requirements.
527-
if (!typeSig) {
528-
success({});
529-
return;
514+
// A non-extension conformance won't have conditional requirements.
515+
const auto ext = dyn_cast<ExtensionDecl>(getDeclContext());
516+
if (!ext) {
517+
return success();
530518
}
531519

532520
// If the extension is invalid, it won't ever get a signature, so we
533521
// "succeed" with an empty result instead.
534522
if (ext->isInvalid()) {
535-
success({});
536-
return;
523+
return success();
524+
}
525+
526+
// A non-generic type won't have conditional requirements.
527+
const auto typeSig = ext->getExtendedNominal()->getGenericSignature();
528+
if (!typeSig) {
529+
return success();
537530
}
538531

539532
// Recursively validating the signature comes up frequently as expanding
@@ -542,28 +535,26 @@ void NormalProtocolConformance::differenceAndStoreConditionalRequirements()
542535
//
543536
// FIXME: In the long run, break this cycle in a more principled way.
544537
if (ext->isComputingGenericSignature()) {
545-
failure();
546-
return;
538+
return failure();
547539
}
548540

549-
auto extensionSig = ext->getGenericSignature();
550-
auto canExtensionSig = extensionSig.getCanonicalSignature();
551-
auto canTypeSig = typeSig.getCanonicalSignature();
552-
if (canTypeSig == canExtensionSig) {
553-
success({});
554-
return;
555-
}
541+
const auto extensionSig = ext->getGenericSignature();
556542

557543
// The extension signature should be a superset of the type signature, meaning
558544
// every thing in the type signature either is included too or is implied by
559545
// something else. The most important bit is having the same type
560546
// parameters. (NB. if/when Swift gets parameterized extensions, this needs to
561547
// change.)
562-
assert(canTypeSig.getGenericParams() == canExtensionSig.getGenericParams());
548+
assert(typeSig->getCanonicalSignature().getGenericParams() ==
549+
extensionSig->getCanonicalSignature().getGenericParams());
563550

564551
// Find the requirements in the extension that aren't proved by the original
565552
// type, these are the ones that make the conformance conditional.
566-
success(ctxt.AllocateCopy(extensionSig->requirementsNotSatisfiedBy(typeSig)));
553+
const auto unsatReqs = extensionSig->requirementsNotSatisfiedBy(typeSig);
554+
if (unsatReqs.empty())
555+
return success();
556+
557+
return success(getProtocol()->getASTContext().AllocateCopy(unsatReqs));
567558
}
568559

569560
void NormalProtocolConformance::setSignatureConformances(

0 commit comments

Comments
 (0)