Skip to content

Commit 4accf59

Browse files
authored
Merge pull request #30618 from CodaFi/protocol-adoption-program
[NFC] Add LookupConformancesInContextRequest
2 parents 4981da4 + 4de729f commit 4accf59

File tree

9 files changed

+106
-40
lines changed

9 files changed

+106
-40
lines changed

include/swift/AST/DeclContext.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -552,31 +552,30 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
552552
///
553553
/// \param lookupKind The kind of lookup to perform.
554554
///
555-
/// \param diagnostics If non-null, will be populated with the set of
556-
/// diagnostics that should be emitted for this declaration context.
557555
/// FIXME: This likely makes more sense on IterableDeclContext or
558556
/// something similar.
559557
SmallVector<ProtocolDecl *, 2>
560558
getLocalProtocols(ConformanceLookupKind lookupKind
561-
= ConformanceLookupKind::All,
562-
SmallVectorImpl<ConformanceDiagnostic> *diagnostics
563-
= nullptr) const;
559+
= ConformanceLookupKind::All) const;
564560

565561
/// Retrieve the set of protocol conformances associated with this
566562
/// declaration context.
567563
///
568564
/// \param lookupKind The kind of lookup to perform.
569565
///
570-
/// \param diagnostics If non-null, will be populated with the set of
571-
/// diagnostics that should be emitted for this declaration context.
572-
///
573566
/// FIXME: This likely makes more sense on IterableDeclContext or
574567
/// something similar.
575568
SmallVector<ProtocolConformance *, 2>
576569
getLocalConformances(ConformanceLookupKind lookupKind
577-
= ConformanceLookupKind::All,
578-
SmallVectorImpl<ConformanceDiagnostic> *diagnostics
579-
= nullptr) const;
570+
= ConformanceLookupKind::All) const;
571+
572+
/// Retrieve diagnostics discovered while expanding conformances for this
573+
/// declaration context. This operation then removes those diagnostics from
574+
/// consideration, so subsequent calls to this function with the same
575+
/// declaration context that have not had any new extensions bound
576+
/// will see an empty array.
577+
SmallVector<ConformanceDiagnostic, 4>
578+
takeConformanceDiagnostics() const;
580579

581580
/// Retrieves a list of separately imported overlays which are shadowing
582581
/// \p declaring. If any \p overlays are returned, qualified lookups into

include/swift/AST/TypeCheckRequests.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,6 +2185,39 @@ class ClosureHasExplicitResultRequest
21852185
bool isCached() const { return true; }
21862186
};
21872187

2188+
using ProtocolConformanceLookupResult = SmallVector<ProtocolConformance *, 2>;
2189+
void simple_display(llvm::raw_ostream &out, ConformanceLookupKind kind);
2190+
2191+
/// Lookup and expand all conformances in the given context.
2192+
///
2193+
/// This request specifically accomodates algorithms for retrieving all
2194+
/// conformances in the primary, even those that are unstated in source but
2195+
/// are implied by other conformances, inherited from other types, or synthesized
2196+
/// by the compiler. A simple case of this is the following:
2197+
///
2198+
/// \code
2199+
/// protocol P {}
2200+
/// protocol Q : P {}
2201+
/// extension T : Q {}
2202+
/// \endcode
2203+
///
2204+
/// Here, a conformance to \c Q has been stated, but a conformance to \c P
2205+
/// must also be reported so it can be checked as well.
2206+
class LookupAllConformancesInContextRequest :
2207+
public SimpleRequest<LookupAllConformancesInContextRequest,
2208+
ProtocolConformanceLookupResult(const DeclContext *),
2209+
CacheKind::Uncached> {
2210+
public:
2211+
using SimpleRequest::SimpleRequest;
2212+
2213+
private:
2214+
friend SimpleRequest;
2215+
2216+
// Evaluation.
2217+
llvm::Expected<ProtocolConformanceLookupResult>
2218+
evaluate(Evaluator &evaluator, const DeclContext *DC) const;
2219+
};
2220+
21882221
// Allow AnyValue to compare two Type values, even though Type doesn't
21892222
// support ==.
21902223
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,6 @@ SWIFT_REQUEST(TypeChecker, ScopedImportLookupRequest,
236236
ArrayRef<ValueDecl *>(ImportDecl *), Cached, NoLocationInfo)
237237
SWIFT_REQUEST(TypeChecker, ClosureHasExplicitResultRequest,
238238
bool(ClosureExpr *), Cached, NoLocationInfo)
239+
SWIFT_REQUEST(TypeChecker, LookupAllConformancesInContextRequest,
240+
ProtocolConformanceLookupResult(const DeclContext *),
241+
Uncached, NoLocationInfo)

lib/AST/ProtocolConformance.cpp

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,16 +1327,14 @@ NominalTypeDecl::getSatisfiedProtocolRequirementsForMember(
13271327
}
13281328

13291329
SmallVector<ProtocolDecl *, 2>
1330-
DeclContext::getLocalProtocols(
1331-
ConformanceLookupKind lookupKind,
1332-
SmallVectorImpl<ConformanceDiagnostic> *diagnostics) const
1333-
{
1330+
DeclContext::getLocalProtocols(ConformanceLookupKind lookupKind) const {
13341331
SmallVector<ProtocolDecl *, 2> result;
13351332

13361333
// Dig out the nominal type.
13371334
NominalTypeDecl *nominal = getSelfNominalTypeDecl();
1338-
if (!nominal)
1335+
if (!nominal) {
13391336
return result;
1337+
}
13401338

13411339
// Update to record all potential conformances.
13421340
nominal->prepareConformanceTable();
@@ -1346,28 +1344,29 @@ DeclContext::getLocalProtocols(
13461344
lookupKind,
13471345
&result,
13481346
nullptr,
1349-
diagnostics);
1347+
nullptr);
13501348

13511349
return result;
13521350
}
13531351

13541352
SmallVector<ProtocolConformance *, 2>
1355-
DeclContext::getLocalConformances(
1356-
ConformanceLookupKind lookupKind,
1357-
SmallVectorImpl<ConformanceDiagnostic> *diagnostics) const
1358-
{
1353+
DeclContext::getLocalConformances(ConformanceLookupKind lookupKind) const {
13591354
SmallVector<ProtocolConformance *, 2> result;
13601355

13611356
// Dig out the nominal type.
13621357
NominalTypeDecl *nominal = getSelfNominalTypeDecl();
1363-
if (!nominal)
1358+
if (!nominal) {
13641359
return result;
1360+
}
13651361

13661362
// Protocols only have self-conformances.
13671363
if (auto protocol = dyn_cast<ProtocolDecl>(nominal)) {
1368-
if (protocol->requiresSelfConformanceWitnessTable())
1369-
return { protocol->getASTContext().getSelfConformance(protocol) };
1370-
return { };
1364+
if (protocol->requiresSelfConformanceWitnessTable()) {
1365+
return SmallVector<ProtocolConformance *, 2>{
1366+
protocol->getASTContext().getSelfConformance(protocol)
1367+
};
1368+
}
1369+
return SmallVector<ProtocolConformance *, 2>();
13711370
}
13721371

13731372
// Update to record all potential conformances.
@@ -1378,7 +1377,35 @@ DeclContext::getLocalConformances(
13781377
lookupKind,
13791378
nullptr,
13801379
&result,
1381-
diagnostics);
1380+
nullptr);
1381+
1382+
return result;
1383+
}
1384+
1385+
SmallVector<ConformanceDiagnostic, 4>
1386+
DeclContext::takeConformanceDiagnostics() const {
1387+
SmallVector<ConformanceDiagnostic, 4> result;
1388+
1389+
// Dig out the nominal type.
1390+
NominalTypeDecl *nominal = getSelfNominalTypeDecl();
1391+
if (!nominal) {
1392+
return { };
1393+
}
1394+
1395+
// Protocols are not subject to the checks for supersession.
1396+
if (isa<ProtocolDecl>(nominal)) {
1397+
return { };
1398+
}
1399+
1400+
// Update to record all potential conformances.
1401+
nominal->prepareConformanceTable();
1402+
nominal->ConformanceTable->lookupConformances(
1403+
nominal,
1404+
const_cast<DeclContext *>(this),
1405+
ConformanceLookupKind::All,
1406+
nullptr,
1407+
nullptr,
1408+
&result);
13821409

13831410
return result;
13841411
}

lib/IRGen/GenClass.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,8 +1113,7 @@ namespace {
11131113
void visitConformances(DeclContext *dc) {
11141114
llvm::SmallSetVector<ProtocolDecl *, 2> protocols;
11151115
for (auto conformance : dc->getLocalConformances(
1116-
ConformanceLookupKind::OnlyExplicit,
1117-
nullptr)) {
1116+
ConformanceLookupKind::OnlyExplicit)) {
11181117
ProtocolDecl *proto = conformance->getProtocol();
11191118
getObjCProtocols(proto, protocols);
11201119
}

lib/IRGen/GenDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ IRGenModule::getConstantReferenceForProtocolDescriptor(ProtocolDecl *proto) {
889889

890890
void IRGenModule::addLazyConformances(DeclContext *dc) {
891891
for (const ProtocolConformance *conf :
892-
dc->getLocalConformances(ConformanceLookupKind::All, nullptr)) {
892+
dc->getLocalConformances(ConformanceLookupKind::All)) {
893893
IRGen.addLazyWitnessTable(conf);
894894
}
895895
}

lib/SILGen/SILGenType.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,7 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
10281028
// Emit witness tables for conformances of concrete types. Protocol types
10291029
// are existential and do not have witness tables.
10301030
for (auto *conformance : theType->getLocalConformances(
1031-
ConformanceLookupKind::NonInherited, nullptr)) {
1031+
ConformanceLookupKind::NonInherited)) {
10321032
if (conformance->isComplete()) {
10331033
if (auto *normal = dyn_cast<NormalProtocolConformance>(conformance))
10341034
SGM.getWitnessTable(normal);
@@ -1152,8 +1152,7 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
11521152
// Emit witness tables for protocol conformances introduced by the
11531153
// extension.
11541154
for (auto *conformance : e->getLocalConformances(
1155-
ConformanceLookupKind::All,
1156-
nullptr)) {
1155+
ConformanceLookupKind::All)) {
11571156
if (conformance->isComplete()) {
11581157
if (auto *normal =dyn_cast<NormalProtocolConformance>(conformance))
11591158
SGM.getWitnessTable(normal);

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5066,6 +5066,12 @@ diagnoseMissingAppendInterpolationMethod(NominalTypeDecl *typeDecl) {
50665066
}
50675067
}
50685068

5069+
llvm::Expected<SmallVector<ProtocolConformance *, 2>>
5070+
LookupAllConformancesInContextRequest::evaluate(
5071+
Evaluator &eval, const DeclContext *DC) const {
5072+
return DC->getLocalConformances(ConformanceLookupKind::All);
5073+
}
5074+
50695075
void TypeChecker::checkConformancesInContext(DeclContext *dc,
50705076
IterableDeclContext *idc) {
50715077
// For anything imported from Clang, lazily check conformances.
@@ -5092,9 +5098,9 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,
50925098
tracker = SF->getReferencedNameTracker();
50935099

50945100
// Check each of the conformances associated with this context.
5095-
SmallVector<ConformanceDiagnostic, 4> diagnostics;
5096-
auto conformances = dc->getLocalConformances(ConformanceLookupKind::All,
5097-
&diagnostics);
5101+
auto conformances =
5102+
evaluateOrDefault(dc->getASTContext().evaluator,
5103+
LookupAllConformancesInContextRequest{dc}, {});
50985104

50995105
// The conformance checker bundle that checks all conformances in the context.
51005106
auto &Context = dc->getASTContext();
@@ -5151,7 +5157,7 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,
51515157
groupChecker.getUnsatisfiedRequirements().end());
51525158

51535159
// Diagnose any conflicts attributed to this declaration context.
5154-
for (const auto &diag : diagnostics) {
5160+
for (const auto &diag : dc->takeConformanceDiagnostics()) {
51555161
// Figure out the declaration of the existing conformance.
51565162
Decl *existingDecl = dyn_cast<NominalTypeDecl>(diag.ExistingDC);
51575163
if (!existingDecl)

lib/Serialization/Serialization.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,7 +2839,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
28392839
extendedType = extendedType->getCanonicalType();
28402840

28412841
auto conformances = extension->getLocalConformances(
2842-
ConformanceLookupKind::All, nullptr);
2842+
ConformanceLookupKind::All);
28432843

28442844
SmallVector<TypeID, 8> inheritedAndDependencyTypes;
28452845
for (auto inherited : extension->getInherited()) {
@@ -3073,7 +3073,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
30733073
auto contextID = S.addDeclContextRef(theStruct->getDeclContext());
30743074

30753075
auto conformances = theStruct->getLocalConformances(
3076-
ConformanceLookupKind::All, nullptr);
3076+
ConformanceLookupKind::All);
30773077

30783078
SmallVector<TypeID, 4> inheritedAndDependencyTypes;
30793079
for (auto inherited : theStruct->getInherited()) {
@@ -3118,7 +3118,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
31183118
auto contextID = S.addDeclContextRef(theEnum->getDeclContext());
31193119

31203120
auto conformances = theEnum->getLocalConformances(
3121-
ConformanceLookupKind::All, nullptr);
3121+
ConformanceLookupKind::All);
31223122

31233123
SmallVector<TypeID, 4> inheritedAndDependencyTypes;
31243124
for (auto inherited : theEnum->getInherited()) {
@@ -3176,7 +3176,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
31763176
auto contextID = S.addDeclContextRef(theClass->getDeclContext());
31773177

31783178
auto conformances = theClass->getLocalConformances(
3179-
ConformanceLookupKind::NonInherited, nullptr);
3179+
ConformanceLookupKind::NonInherited);
31803180

31813181
SmallVector<TypeID, 4> inheritedAndDependencyTypes;
31823182
for (auto inherited : theClass->getInherited()) {

0 commit comments

Comments
 (0)