Skip to content

Commit 971a6e3

Browse files
committed
[Name lookup] Use decl-based name lookup for the conformance lookup table.
Add API to get all of the nominal types directly referenced from the inheritance clause of a given declaration. Use that to find the protocols to enter into the conformance lookup table based on a given declaration, without going through the type checker [*]. [*] Except for unqualified lookup still needing to use the type checker.
1 parent 199bf6e commit 971a6e3

File tree

4 files changed

+76
-17
lines changed

4 files changed

+76
-17
lines changed

include/swift/AST/NameLookup.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,24 @@ void lookupInModule(ModuleDecl *module, ModuleDecl::AccessPathTy accessPath,
351351
ArrayRef<ModuleDecl::ImportedModule> extraImports = {});
352352

353353
} // end namespace namelookup
354+
355+
/// Retrieve the set of nominal type declarations that are directly
356+
/// "inherited" by the given declaration at a particular position in the
357+
/// list of "inherited" types.
358+
///
359+
/// Add anything we find to the
360+
void getDirectlyInheritedNominalTypeDecls(
361+
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
362+
unsigned i,
363+
llvm::SmallVectorImpl<std::pair<SourceLoc, NominalTypeDecl *>> &result);
364+
365+
/// Retrieve the set of nominal type declarations that are directly
366+
/// "inherited" by the given declaration, looking through typealiases
367+
/// and splitting out the components of compositions.
368+
SmallVector<std::pair<SourceLoc, NominalTypeDecl *>, 4>
369+
getDirectlyInheritedNominalTypeDecls(
370+
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl);
371+
354372
} // end namespace swift
355373

356374
#endif

lib/AST/ConformanceLookupTable.cpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ExistentialLayout.h"
2121
#include "swift/AST/LazyResolver.h"
2222
#include "swift/AST/Module.h"
23+
#include "swift/AST/NameLookup.h"
2324
#include "swift/AST/ProtocolConformance.h"
2425
#include "swift/AST/ProtocolConformanceRef.h"
2526
#include "llvm/Support/SaveAndRestore.h"
@@ -488,22 +489,10 @@ bool ConformanceLookupTable::addProtocol(ProtocolDecl *protocol, SourceLoc loc,
488489
void ConformanceLookupTable::addInheritedProtocols(
489490
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
490491
ConformanceSource source) {
491-
// Visit each of the types in the inheritance list to find
492-
// protocols.
493-
auto typeDecl = decl.dyn_cast<TypeDecl *>();
494-
auto extDecl = decl.dyn_cast<ExtensionDecl *>();
495-
unsigned numInherited = typeDecl ? typeDecl->getInherited().size()
496-
: extDecl->getInherited().size();
497-
for (auto index : range(numInherited)) {
498-
Type inheritedType = typeDecl ? typeDecl->getInheritedType(index)
499-
: extDecl->getInheritedType(index);
500-
if (!inheritedType || !inheritedType->isExistentialType())
501-
continue;
502-
SourceLoc loc = typeDecl ? typeDecl->getInherited()[index].getLoc()
503-
: extDecl->getInherited()[index].getLoc();
504-
auto layout = inheritedType->getExistentialLayout();
505-
for (auto *proto : layout.getProtocols())
506-
addProtocol(proto->getDecl(), loc, source);
492+
// Find all of the protocols in the inheritance list.
493+
for (const auto &found : getDirectlyInheritedNominalTypeDecls(decl)) {
494+
if (auto proto = dyn_cast<ProtocolDecl>(found.second))
495+
addProtocol(proto, found.first, source);
507496
}
508497
}
509498

lib/AST/NameLookup.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,3 +2277,53 @@ NominalTypeDecl *ExtendedNominalRequest::evaluate(Evaluator &evaluator,
22772277
= resolveTypeDeclsToNominal(evaluator, ctx, referenced, modulesFound);
22782278
return nominalTypes.empty() ? nullptr : nominalTypes.front();
22792279
}
2280+
2281+
void swift::getDirectlyInheritedNominalTypeDecls(
2282+
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
2283+
unsigned i,
2284+
llvm::SmallVectorImpl<std::pair<SourceLoc, NominalTypeDecl *>> &result) {
2285+
auto typeDecl = decl.dyn_cast<TypeDecl *>();
2286+
auto extDecl = decl.dyn_cast<ExtensionDecl *>();
2287+
2288+
ASTContext &ctx = typeDecl ? typeDecl->getASTContext()
2289+
: extDecl->getASTContext();
2290+
2291+
// Find inherited declarations.
2292+
auto referenced = ctx.evaluator(InheritedDeclsReferencedRequest{decl, i});
2293+
2294+
// Resolve those type declarations to nominal type declarations.
2295+
SmallVector<ModuleDecl *, 2> modulesFound;
2296+
auto nominalTypes
2297+
= resolveTypeDeclsToNominal(ctx.evaluator, ctx, referenced, modulesFound);
2298+
2299+
// Dig out the source location
2300+
// FIXME: This is a hack. We need cooperation from
2301+
// InheritedDeclsReferencedRequest to make this work.
2302+
SourceLoc loc;
2303+
if (TypeRepr *typeRepr = typeDecl ? typeDecl->getInherited()[i].getTypeRepr()
2304+
: extDecl->getInherited()[i].getTypeRepr()){
2305+
loc = typeRepr->getLoc();
2306+
}
2307+
2308+
// Form the result.
2309+
for (auto nominal : nominalTypes) {
2310+
result.push_back({loc, nominal});
2311+
}
2312+
}
2313+
2314+
SmallVector<std::pair<SourceLoc, NominalTypeDecl *>, 4>
2315+
swift::getDirectlyInheritedNominalTypeDecls(
2316+
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl) {
2317+
auto typeDecl = decl.dyn_cast<TypeDecl *>();
2318+
auto extDecl = decl.dyn_cast<ExtensionDecl *>();
2319+
2320+
// Gather results from all of the inherited types.
2321+
unsigned numInherited = typeDecl ? typeDecl->getInherited().size()
2322+
: extDecl->getInherited().size();
2323+
SmallVector<std::pair<SourceLoc, NominalTypeDecl *>, 4> result;
2324+
for (unsigned i : range(numInherited)) {
2325+
getDirectlyInheritedNominalTypeDecls(decl, i, result);
2326+
}
2327+
2328+
return result;
2329+
}

test/decl/inherit/inherit.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ struct S2 : struct { } // expected-error{{expected type}}
4646
struct S3 : P, P & Q { } // expected-error {{redundant conformance of 'S3' to protocol 'P'}}
4747
// expected-error @-1 {{non-class type 'S3' cannot conform to class protocol 'Q'}}
4848
// expected-note @-2 {{'S3' declares conformance to protocol 'P' here}}
49-
struct S4 : P, P { } // expected-error {{duplicate inheritance from 'P'}}
49+
struct S4 : P, P { } // FIXME: expected-error {{duplicate inheritance from 'P'}}
50+
// expected-error@-1{{redundant conformance of 'S4' to protocol 'P'}}
51+
// expected-note@-2{{'S4' declares conformance to protocol 'P' here}}
5052
struct S6 : P & { } // expected-error {{expected identifier for type name}}
5153
struct S7 : protocol<P, Q> { } // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}}
5254
// expected-error @-1 {{non-class type 'S7' cannot conform to class protocol 'Q'}}

0 commit comments

Comments
 (0)