Skip to content

Commit 28d1455

Browse files
committed
AST: Re-implement associated conformance storage in preparation for AssociatedConformanceRequest
1 parent 61730af commit 28d1455

File tree

4 files changed

+46
-94
lines changed

4 files changed

+46
-94
lines changed

include/swift/AST/ProtocolConformance.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,6 @@ class NormalProtocolConformance : public RootProtocolConformance,
480480

481481
/// Conformances that satisfy each of conformance requirements of the
482482
/// requirement signature of the protocol.
483-
ArrayRef<ProtocolConformanceRef> SignatureConformances;
484483
MutableArrayRef<llvm::Optional<ProtocolConformanceRef>> AssociatedConformances;
485484

486485
/// The lazy member loader provides callbacks for populating imported and
@@ -545,7 +544,6 @@ class NormalProtocolConformance : public RootProtocolConformance,
545544
/// Mark this conformance as invalid.
546545
void setInvalid() {
547546
ContextAndBits.setInt(ContextAndBits.getInt() | InvalidFlag);
548-
SignatureConformances = {};
549547
}
550548

551549
/// Whether this is an "unchecked" conformance.
@@ -666,19 +664,6 @@ class NormalProtocolConformance : public RootProtocolConformance,
666664
/// Override the witness for a given requirement.
667665
void overrideWitness(ValueDecl *requirement, Witness newWitness);
668666

669-
/// Retrieve the protocol conformances that satisfy the requirements of the
670-
/// protocol, which line up with the conformance constraints in the
671-
/// protocol's requirement signature.
672-
ArrayRef<ProtocolConformanceRef> getSignatureConformances() const {
673-
if (Loader)
674-
resolveLazyInfo();
675-
return SignatureConformances;
676-
}
677-
678-
/// Copy the given protocol conformances for the requirement signature into
679-
/// the normal conformance.
680-
void setSignatureConformances(ArrayRef<ProtocolConformanceRef> conformances);
681-
682667
/// Populate the signature conformances without checking if they satisfy
683668
/// requirements. Can only be used with parsed or imported conformances.
684669
void finishSignatureConformances();

lib/AST/ProtocolConformance.cpp

Lines changed: 45 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -388,34 +388,6 @@ ConditionalRequirementsRequest::evaluate(Evaluator &evaluator,
388388
return NPC->getProtocol()->getASTContext().AllocateCopy(unsatReqs);
389389
}
390390

391-
void NormalProtocolConformance::setSignatureConformances(
392-
ArrayRef<ProtocolConformanceRef> conformances) {
393-
if (conformances.empty()) {
394-
SignatureConformances = { };
395-
return;
396-
}
397-
398-
auto &ctx = getProtocol()->getASTContext();
399-
SignatureConformances = ctx.AllocateCopy(conformances);
400-
401-
#if !NDEBUG
402-
unsigned idx = 0;
403-
auto reqs = getProtocol()->getRequirementSignature().getRequirements();
404-
for (const auto &req : reqs) {
405-
if (req.getKind() == RequirementKind::Conformance) {
406-
assert(!conformances[idx].isConcrete() ||
407-
!conformances[idx].getConcrete()->getType()->hasArchetype() &&
408-
"Should have interface types here");
409-
assert(idx < conformances.size());
410-
assert(conformances[idx].isInvalid() ||
411-
conformances[idx].getRequirement() == req.getProtocolDecl());
412-
++idx;
413-
}
414-
}
415-
assert(idx == conformances.size() && "Too many conformances");
416-
#endif
417-
}
418-
419391
void NormalProtocolConformance::resolveLazyInfo() const {
420392
assert(Loader);
421393

@@ -552,14 +524,12 @@ NormalProtocolConformance::getAssociatedConformance(Type assocType,
552524
[&](Type t, ProtocolDecl *p, unsigned index) {
553525
if (t->isEqual(assocType) && p == protocol) {
554526
// Fill in the signature conformances, if we haven't done so yet.
555-
if (getSignatureConformances().empty()) {
556-
const_cast<NormalProtocolConformance *>(this)->finishSignatureConformances();
527+
if (!hasComputedAssociatedConformances()) {
528+
const_cast<NormalProtocolConformance *>(this)
529+
->finishSignatureConformances();
557530
}
558531

559-
assert(!getSignatureConformances().empty() &&
560-
"signature conformances not yet computed");
561-
562-
result = getSignatureConformances()[index];
532+
result = getAssociatedConformance(index);
563533
return true;
564534
}
565535

@@ -639,55 +609,53 @@ recursivelySubstituteBaseType(ModuleDecl *module,
639609

640610
/// Collect conformances for the requirement signature.
641611
void NormalProtocolConformance::finishSignatureConformances() {
642-
if (!SignatureConformances.empty())
643-
return;
612+
if (Loader)
613+
resolveLazyInfo();
644614

645-
auto *proto = getProtocol();
646-
auto reqSig = proto->getRequirementSignature().getRequirements();
647-
if (reqSig.empty())
615+
if (hasComputedAssociatedConformances())
648616
return;
649617

650-
SmallVector<ProtocolConformanceRef, 4> reqConformances;
651-
for (const auto &req : reqSig) {
652-
if (req.getKind() != RequirementKind::Conformance)
653-
continue;
618+
createAssociatedConformanceArray();
654619

655-
ModuleDecl *module = getDeclContext()->getParentModule();
620+
auto *proto = getProtocol();
621+
ModuleDecl *module = getDeclContext()->getParentModule();
656622

657-
Type substTy;
658-
auto origTy = req.getFirstType();
659-
if (origTy->isEqual(proto->getSelfInterfaceType())) {
660-
substTy = getType();
661-
} else {
662-
auto *depMemTy = origTy->castTo<DependentMemberType>();
663-
substTy = recursivelySubstituteBaseType(module, this, depMemTy);
664-
}
665-
auto reqProto = req.getProtocolDecl();
623+
forEachAssociatedConformance(
624+
[&](Type origTy, ProtocolDecl *reqProto, unsigned index) {
625+
Type substTy;
626+
627+
if (origTy->isEqual(proto->getSelfInterfaceType())) {
628+
substTy = getType();
629+
} else {
630+
auto *depMemTy = origTy->castTo<DependentMemberType>();
631+
substTy = recursivelySubstituteBaseType(module, this, depMemTy);
632+
}
666633

667-
// Looking up a conformance for a contextual type and mapping the
668-
// conformance context produces a more accurate result than looking
669-
// up a conformance from an interface type.
670-
//
671-
// This can happen if the conformance has an associated conformance
672-
// depending on an associated type that is made concrete in a
673-
// refining protocol.
674-
//
675-
// That is, the conformance of an interface type G<T> : P really
676-
// depends on the generic signature of the current context, because
677-
// performing the lookup in a "more" constrained extension than the
678-
// one where the conformance was defined must produce concrete
679-
// conformances.
680-
//
681-
// FIXME: Eliminate this, perhaps by adding a variant of
682-
// lookupConformance() taking a generic signature.
683-
if (substTy->hasTypeParameter())
684-
substTy = getDeclContext()->mapTypeIntoContext(substTy);
685-
686-
reqConformances.push_back(module->lookupConformance(substTy, reqProto,
687-
/*allowMissing=*/true)
688-
.mapConformanceOutOfContext());
689-
}
690-
setSignatureConformances(reqConformances);
634+
// Looking up a conformance for a contextual type and mapping the
635+
// conformance context produces a more accurate result than looking
636+
// up a conformance from an interface type.
637+
//
638+
// This can happen if the conformance has an associated conformance
639+
// depending on an associated type that is made concrete in a
640+
// refining protocol.
641+
//
642+
// That is, the conformance of an interface type G<T> : P really
643+
// depends on the generic signature of the current context, because
644+
// performing the lookup in a "more" constrained extension than the
645+
// one where the conformance was defined must produce concrete
646+
// conformances.
647+
//
648+
// FIXME: Eliminate this, perhaps by adding a variant of
649+
// lookupConformance() taking a generic signature.
650+
if (substTy->hasTypeParameter())
651+
substTy = getDeclContext()->mapTypeIntoContext(substTy);
652+
653+
auto assocConf = module->lookupConformance(substTy, reqProto,
654+
/*allowMissing=*/true)
655+
.mapConformanceOutOfContext();
656+
setAssociatedConformance(index, assocConf);
657+
return false;
658+
});
691659
}
692660

693661
Witness RootProtocolConformance::getWitness(ValueDecl *requirement) const {

lib/AST/SubstitutionMap.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
433433
auto normal = concrete->getRootNormalConformance();
434434

435435
// If we haven't set the signature conformances yet, force the issue now.
436-
if (normal->getSignatureConformances().empty()) {
436+
if (!normal->hasComputedAssociatedConformances()) {
437437
// If we're in the process of checking the type witnesses, fail
438438
// gracefully.
439439
// FIXME: Seems like we should be able to get at the intermediate state

lib/Serialization/Deserialization.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7988,7 +7988,6 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
79887988
llvm::inconvertibleErrorCode()));
79897989
}
79907990
}
7991-
conformance->setSignatureConformances(reqConformances);
79927991

79937992
for (unsigned index : indices(reqConformances)) {
79947993
conformance->setAssociatedConformance(index, reqConformances[index]);

0 commit comments

Comments
 (0)