Skip to content

Commit a3fa3bf

Browse files
authored
Merge pull request swiftlang#69038 from slavapestov/clean-up-associated-conformances
Preparation for lazily populating associated conformances
2 parents 4c5b681 + 3a5c96d commit a3fa3bf

17 files changed

+441
-244
lines changed

include/swift/AST/ProtocolConformance.h

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,27 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance
191191
return false;
192192
}
193193

194+
/// Apply the given function object to each associated conformance requirement
195+
/// within this protocol conformance.
196+
///
197+
/// \returns true if the function ever returned true
198+
template<typename F>
199+
bool forEachAssociatedConformance(F f) const {
200+
const ProtocolDecl *protocol = getProtocol();
201+
unsigned index = 0;
202+
for (auto req : protocol->getRequirementSignature().getRequirements()) {
203+
if (req.getKind() != RequirementKind::Conformance)
204+
continue;
205+
206+
if (f(req.getFirstType(), req.getProtocolDecl(), index))
207+
return true;
208+
209+
++index;
210+
}
211+
212+
return false;
213+
}
214+
194215
/// Retrieve the value witness declaration corresponding to the given
195216
/// requirement.
196217
ValueDecl *getWitnessDecl(ValueDecl *requirement) const;
@@ -423,13 +444,18 @@ class NormalProtocolConformance : public RootProtocolConformance,
423444

424445
/// The conformance was labeled with @unchecked.
425446
UncheckedFlag = 0x02,
447+
448+
/// We have allocated the AssociatedConformances array (but not necessarily
449+
/// populated any of its elements).
450+
HasComputedAssociatedConformancesFlag = 0x04,
426451
};
427452

428453
/// The declaration context containing the ExtensionDecl or
429454
/// NominalTypeDecl that declared the conformance.
430455
///
431-
/// Also stores the "invalid" and "unchecked" bits.
432-
llvm::PointerIntPair<DeclContext *, 2, unsigned> ContextAndBits;
456+
/// Also stores the "invalid", "unchecked" and "has computed associated
457+
/// conformances" bits.
458+
llvm::PointerIntPair<DeclContext *, 3, unsigned> ContextAndBits;
433459

434460
/// The reason that this conformance exists.
435461
///
@@ -454,7 +480,7 @@ class NormalProtocolConformance : public RootProtocolConformance,
454480

455481
/// Conformances that satisfy each of conformance requirements of the
456482
/// requirement signature of the protocol.
457-
ArrayRef<ProtocolConformanceRef> SignatureConformances;
483+
MutableArrayRef<llvm::Optional<ProtocolConformanceRef>> AssociatedConformances;
458484

459485
/// The lazy member loader provides callbacks for populating imported and
460486
/// deserialized conformances.
@@ -518,7 +544,6 @@ class NormalProtocolConformance : public RootProtocolConformance,
518544
/// Mark this conformance as invalid.
519545
void setInvalid() {
520546
ContextAndBits.setInt(ContextAndBits.getInt() | InvalidFlag);
521-
SignatureConformances = {};
522547
}
523548

524549
/// Whether this is an "unchecked" conformance.
@@ -533,6 +558,17 @@ class NormalProtocolConformance : public RootProtocolConformance,
533558
ContextAndBits.setInt(ContextAndBits.getInt() | UncheckedFlag);
534559
}
535560

561+
/// Determine whether we've lazily computed the associated conformance array
562+
/// already.
563+
bool hasComputedAssociatedConformances() const {
564+
return ContextAndBits.getInt() & HasComputedAssociatedConformancesFlag;
565+
}
566+
567+
/// Mark this conformance as having computed the assocaited conformance array.
568+
void setHasComputedAssociatedConformances() {
569+
ContextAndBits.setInt(ContextAndBits.getInt() | HasComputedAssociatedConformancesFlag);
570+
}
571+
536572
/// Get the kind of source from which this conformance comes.
537573
ConformanceEntryKind getSourceKind() const {
538574
return SourceKindAndImplyingConformance.getInt();
@@ -599,6 +635,16 @@ class NormalProtocolConformance : public RootProtocolConformance,
599635
ProtocolConformanceRef
600636
getAssociatedConformance(Type assocType, ProtocolDecl *protocol) const;
601637

638+
/// Allocate the backing array if needed, computing its size from the
639+
///protocol's requirement signature.
640+
void createAssociatedConformanceArray();
641+
642+
llvm::Optional<ProtocolConformanceRef>
643+
getAssociatedConformance(unsigned index) const;
644+
645+
void
646+
setAssociatedConformance(unsigned index, ProtocolConformanceRef assocConf);
647+
602648
/// Retrieve the value witness corresponding to the given requirement.
603649
Witness getWitness(ValueDecl *requirement) const;
604650

@@ -618,19 +664,6 @@ class NormalProtocolConformance : public RootProtocolConformance,
618664
/// Override the witness for a given requirement.
619665
void overrideWitness(ValueDecl *requirement, Witness newWitness);
620666

621-
/// Retrieve the protocol conformances that satisfy the requirements of the
622-
/// protocol, which line up with the conformance constraints in the
623-
/// protocol's requirement signature.
624-
ArrayRef<ProtocolConformanceRef> getSignatureConformances() const {
625-
if (Loader)
626-
resolveLazyInfo();
627-
return SignatureConformances;
628-
}
629-
630-
/// Copy the given protocol conformances for the requirement signature into
631-
/// the normal conformance.
632-
void setSignatureConformances(ArrayRef<ProtocolConformanceRef> conformances);
633-
634667
/// Populate the signature conformances without checking if they satisfy
635668
/// requirements. Can only be used with parsed or imported conformances.
636669
void finishSignatureConformances();

include/swift/AST/TypeCheckRequests.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2737,6 +2737,30 @@ class ValueWitnessRequest
27372737
void cacheResult(Witness value) const;
27382738
};
27392739

2740+
class AssociatedConformanceRequest
2741+
: public SimpleRequest<AssociatedConformanceRequest,
2742+
ProtocolConformanceRef(NormalProtocolConformance *,
2743+
CanType, ProtocolDecl *,
2744+
unsigned),
2745+
RequestFlags::SeparatelyCached> {
2746+
public:
2747+
using SimpleRequest::SimpleRequest;
2748+
2749+
private:
2750+
friend SimpleRequest;
2751+
2752+
// Evaluation.
2753+
ProtocolConformanceRef
2754+
evaluate(Evaluator &evaluator, NormalProtocolConformance *conformance,
2755+
CanType t, ProtocolDecl *proto, unsigned index) const;
2756+
2757+
public:
2758+
// Separate caching.
2759+
bool isCached() const { return true; }
2760+
llvm::Optional<ProtocolConformanceRef> getCachedResult() const;
2761+
void cacheResult(ProtocolConformanceRef value) const;
2762+
};
2763+
27402764
struct PreCheckResultBuilderDescriptor {
27412765
AnyFunctionRef Fn;
27422766
bool SuppressDiagnostics;

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,10 @@ SWIFT_REQUEST(TypeChecker, TypeWitnessRequest,
403403
TypeWitnessAndDecl(NormalProtocolConformance *,
404404
AssociatedTypeDecl *),
405405
SeparatelyCached, NoLocationInfo)
406+
SWIFT_REQUEST(TypeChecker, AssociatedConformanceRequest,
407+
ProtocolConformanceRef(NormalProtocolConformance *,
408+
Type, ProtocolDecl *, unsigned),
409+
SeparatelyCached, NoLocationInfo)
406410
SWIFT_REQUEST(TypeChecker, ValueWitnessRequest,
407411
Witness(NormalProtocolConformance *, ValueDecl *),
408412
SeparatelyCached, NoLocationInfo)

lib/AST/ASTDumper.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3414,7 +3414,8 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, StringRef>,
34143414
});
34153415
}
34163416

3417-
printRecRange(T->getGenericArguments(), "generic_arguments");
3417+
for (auto arg : T->getGenericArguments())
3418+
printRec(arg);
34183419

34193420
printFoot();
34203421
}
@@ -3549,6 +3550,7 @@ class PrintConformance : public PrintBase {
35493550
});
35503551
return false;
35513552
});
3553+
35523554
normal->forEachValueWitness([&](const ValueDecl *req,
35533555
Witness witness) {
35543556
printRecArbitrary([&](StringRef label) {
@@ -3566,9 +3568,17 @@ class PrintConformance : public PrintBase {
35663568
});
35673569
});
35683570

3569-
for (auto sigConf : normal->getSignatureConformances()) {
3570-
printRec(sigConf, visited);
3571-
}
3571+
normal->forEachAssociatedConformance(
3572+
[&](Type t, ProtocolDecl *proto, unsigned index) {
3573+
printRecArbitrary([&](StringRef label) {
3574+
printHead("assoc_conformance", ASTNodeColor, label);
3575+
printFieldQuoted(t, "type", TypeColor);
3576+
printFieldQuoted(proto->getName(), "proto");
3577+
printRec(normal->getAssociatedConformance(t, proto), visited);
3578+
printFoot();
3579+
});
3580+
return false;
3581+
});
35723582
}
35733583

35743584
if (auto condReqs = normal->getConditionalRequirementsIfAvailable()) {
@@ -3886,14 +3896,16 @@ namespace {
38863896

38873897
printFieldQuoted(T->getDecl()->printRef(), "decl");
38883898
if (auto underlying = T->getSinglyDesugaredType()) {
3889-
printField(underlying, "underlying", TypeColor);
3899+
printRec(underlying, "underlying");
38903900
} else {
3901+
// This can't actually happen
38913902
printFlag("unresolved_underlying");
38923903
}
38933904

38943905
if (T->getParent())
38953906
printRec(T->getParent(), "parent");
3896-
printRecRange(T->getDirectGenericArgs(), "direct_generic_args");
3907+
for (auto arg : T->getDirectGenericArgs())
3908+
printRec(arg);
38973909

38983910
printFoot();
38993911
}

lib/AST/ASTVerifier.cpp

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2879,40 +2879,6 @@ class Verifier : public ASTWalker {
28792879
continue;
28802880
}
28812881
}
2882-
2883-
// Make sure we have the right signature conformances.
2884-
if (!normal->isInvalid()){
2885-
auto conformances = normal->getSignatureConformances();
2886-
unsigned idx = 0;
2887-
auto reqs = proto->getRequirementSignature().getRequirements();
2888-
for (const auto &req : reqs) {
2889-
if (req.getKind() != RequirementKind::Conformance)
2890-
continue;
2891-
2892-
if (idx >= conformances.size()) {
2893-
Out << "error: not enough conformances for requirement signature\n";
2894-
normal->dump(Out);
2895-
abort();
2896-
}
2897-
2898-
auto reqProto = req.getProtocolDecl();
2899-
if (reqProto != conformances[idx].getRequirement()) {
2900-
Out << "error: wrong protocol in signature conformances: have "
2901-
<< conformances[idx].getRequirement()->getName().str()
2902-
<< ", expected " << reqProto->getName().str()<< "\n";
2903-
normal->dump(Out);
2904-
abort();
2905-
}
2906-
2907-
++idx;
2908-
}
2909-
2910-
if (idx != conformances.size()) {
2911-
Out << "error: too many conformances for requirement signature\n";
2912-
normal->dump(Out);
2913-
abort();
2914-
}
2915-
}
29162882
}
29172883

29182884
void verifyChecked(GenericTypeDecl *generic) {

lib/AST/PrettyStackTrace.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,11 @@ void swift::printConformanceDescription(llvm::raw_ostream &out,
273273
return;
274274
}
275275

276-
out << "protocol conformance to ";
277-
printDeclDescription(out, conformance->getProtocol(), /*newline*/false);
278-
out << " for ";
279-
printTypeDescription(out, conformance->getType(), ctxt, addNewline);
276+
out << "protocol conformance "
277+
<< conformance->getType() << ": "
278+
<< conformance->getProtocol()->getName() << " at ";
279+
auto *decl = conformance->getDeclContext()->getInnermostDeclarationDeclContext();
280+
printDeclDescription(out, decl, addNewline);
280281
}
281282

282283
void swift::printSourceLocDescription(llvm::raw_ostream &out,

0 commit comments

Comments
 (0)