mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Move lookupQualified from Module to DeclContext.
Qualified lookup depends not only on the current module but actually the current file, since imports are file-scoped by default. Currently this only affects lookup into other modules (e.g. "Foundation.NSString"), but this could also be used for extension filtering. This breaks one name resolution test, but the refactoring in the next commit changes everything anyway and will restore the test. Swift SVN r10831
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#ifndef SWIFT_DECLCONTEXT_H
|
||||
#define SWIFT_DECLCONTEXT_H
|
||||
|
||||
#include "swift/AST/Identifier.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
@@ -28,9 +29,11 @@ namespace swift {
|
||||
class ASTWalker;
|
||||
class DeclContext;
|
||||
class GenericParamList;
|
||||
class LazyResolver;
|
||||
class SourceFile;
|
||||
class Type;
|
||||
class Module;
|
||||
class ValueDecl;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
@@ -204,6 +207,33 @@ public:
|
||||
/// Determine whether the innermost context is generic.
|
||||
bool isInnermostContextGeneric() const;
|
||||
|
||||
/// Look for the set of declarations with the given name within a type,
|
||||
/// its extensions and, optionally, its supertypes.
|
||||
///
|
||||
/// This routine performs name lookup within a given type, its extensions
|
||||
/// and, optionally, its supertypes and their extensions, from the perspective
|
||||
/// of the current DeclContext. It can eliminate non-visible, hidden, and
|
||||
/// overridden declarations from the result set. It does not, however, perform
|
||||
/// any filtering based on the semantic usefulness of the results.
|
||||
///
|
||||
/// \param type The type to look into.
|
||||
///
|
||||
/// \param name The name to search for.
|
||||
///
|
||||
/// \param options Options that control name lookup, based on the
|
||||
/// \c NL_* constants in \c NameLookupOptions.
|
||||
///
|
||||
/// \param typeResolver Used to resolve types, usually for overload purposes.
|
||||
/// May be null.
|
||||
///
|
||||
/// \param[out] decls Will be populated with the declarations found by name
|
||||
/// lookup.
|
||||
///
|
||||
/// \returns true if anything was found.
|
||||
bool lookupQualified(Type type, Identifier name, unsigned options,
|
||||
LazyResolver *typeResolver,
|
||||
SmallVectorImpl<ValueDecl *> &decls) const;
|
||||
|
||||
/// getASTContext - Return the ASTContext for a specified DeclContext by
|
||||
/// walking up to the enclosing module and returning its ASTContext.
|
||||
ASTContext &getASTContext();
|
||||
|
||||
@@ -167,32 +167,6 @@ public:
|
||||
VisibleDeclConsumer &Consumer,
|
||||
NLKind LookupKind) const;
|
||||
|
||||
/// Look for the set of declarations with the given name within a type,
|
||||
/// its extensions and, optionally, its supertypes.
|
||||
///
|
||||
/// This routine performs name lookup within a given type, its extensions
|
||||
/// and, optionally, its supertypes and their extensions. It can eliminate
|
||||
/// non-visible, hidden, and overridden declarations from the result set.
|
||||
/// It does not, however, perform any filtering based on the semantic
|
||||
/// usefulness of the results.
|
||||
///
|
||||
/// \param type The type to look into.
|
||||
///
|
||||
/// \param name The name to search for.
|
||||
///
|
||||
/// \param options Options that control name lookup, based on the
|
||||
/// \c NL_* constants in \c NameLookupOptions.
|
||||
///
|
||||
/// \param typeResolver Used to resolve types, usually for overload purposes.
|
||||
///
|
||||
/// \param[out] decls Will be populated with the declarations found by name
|
||||
/// lookup.
|
||||
///
|
||||
/// \returns true if anything was found.
|
||||
bool lookupQualified(Type type, Identifier name, unsigned options,
|
||||
LazyResolver *typeResolver,
|
||||
SmallVectorImpl<ValueDecl *> &decls);
|
||||
|
||||
/// @{
|
||||
|
||||
/// Look up the given operator in this module.
|
||||
@@ -368,6 +342,22 @@ public:
|
||||
/// This does a simple local lookup, not recursively looking through imports.
|
||||
void getTopLevelDecls(SmallVectorImpl<Decl*> &Results) const;
|
||||
|
||||
void forAllVisibleModules(std::function<bool(Module::ImportedModule)> fn);
|
||||
|
||||
void forAllVisibleModules(std::function<void(Module::ImportedModule)> fn) {
|
||||
forAllVisibleModules([=](const Module::ImportedModule &import) -> bool {
|
||||
fn(import);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
void forAllVisibleModules(const Fn &fn) {
|
||||
using RetTy = typename as_function<Fn>::type::result_type;
|
||||
std::function<RetTy(Module::ImportedModule)> wrapped = std::cref(fn);
|
||||
forAllVisibleModules(wrapped);
|
||||
}
|
||||
|
||||
Module *getParentModule() const {
|
||||
return const_cast<Module *>(cast<Module>(getParent()));
|
||||
}
|
||||
|
||||
@@ -1114,6 +1114,20 @@ void Module::forAllVisibleModules(Optional<AccessPathTy> thisPath,
|
||||
forAllImportedModules<true>(this, thisPath, fn);
|
||||
}
|
||||
|
||||
void
|
||||
FileUnit::forAllVisibleModules(std::function<bool(Module::ImportedModule)> fn) {
|
||||
getParentModule()->forAllVisibleModules(Module::AccessPathTy(), fn);
|
||||
|
||||
if (auto SF = dyn_cast<SourceFile>(this)) {
|
||||
// Handle privately visible modules as well.
|
||||
for (auto importPair : SF->getImports()) {
|
||||
if (!importPair.second)
|
||||
importPair.first.second->forAllVisibleModules(importPair.first.first,
|
||||
fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Module::collectLinkLibraries(LinkLibraryCallback callback) {
|
||||
forAllImportedModules<false>(this, AccessPathTy(),
|
||||
[=](ImportedModule import) -> bool {
|
||||
|
||||
@@ -385,7 +385,7 @@ UnqualifiedLookup::UnqualifiedLookup(Identifier Name, DeclContext *DC,
|
||||
TypeResolver->resolveDeclSignature(BaseDecl);
|
||||
|
||||
SmallVector<ValueDecl *, 4> Lookup;
|
||||
M.lookupQualified(ExtendedType, Name, NL_UnqualifiedDefault,
|
||||
DC->lookupQualified(ExtendedType, Name, NL_UnqualifiedDefault,
|
||||
TypeResolver, Lookup);
|
||||
bool isMetatypeType = ExtendedType->is<MetaTypeType>();
|
||||
bool FoundAny = false;
|
||||
@@ -688,11 +688,20 @@ ArrayRef<ValueDecl *> NominalTypeDecl::lookupDirect(Identifier name) {
|
||||
return { known->second.begin(), known->second.size() };
|
||||
}
|
||||
|
||||
bool Module::lookupQualified(Type type,
|
||||
template <typename Fn>
|
||||
static void forAllVisibleModules(const DeclContext *DC, const Fn &fn) {
|
||||
DeclContext *moduleScope = DC->getModuleScopeContext();
|
||||
if (auto file = dyn_cast<FileUnit>(moduleScope))
|
||||
file->forAllVisibleModules(fn);
|
||||
else
|
||||
cast<Module>(moduleScope)->forAllVisibleModules(Module::AccessPathTy(), fn);
|
||||
}
|
||||
|
||||
bool DeclContext::lookupQualified(Type type,
|
||||
Identifier name,
|
||||
unsigned options,
|
||||
LazyResolver *typeResolver,
|
||||
SmallVectorImpl<ValueDecl *> &decls) {
|
||||
SmallVectorImpl<ValueDecl *> &decls) const {
|
||||
if (type->is<ErrorType>()) {
|
||||
return false;
|
||||
}
|
||||
@@ -713,8 +722,8 @@ bool Module::lookupQualified(Type type,
|
||||
if (auto moduleTy = type->getAs<ModuleType>()) {
|
||||
Module *module = moduleTy->getModule();
|
||||
// Perform the lookup in all imports of this module.
|
||||
forAllVisibleModules(AccessPathTy(),
|
||||
[&](const ImportedModule &import) -> bool {
|
||||
forAllVisibleModules(this,
|
||||
[&](const Module::ImportedModule &import) -> bool {
|
||||
using namespace namelookup;
|
||||
if (import.second != module)
|
||||
return true;
|
||||
@@ -725,6 +734,7 @@ bool Module::lookupQualified(Type type,
|
||||
// to keep going.
|
||||
return !import.first.empty();
|
||||
});
|
||||
|
||||
std::sort(decls.begin(), decls.end());
|
||||
auto afterUnique = std::unique(decls.begin(), decls.end());
|
||||
decls.erase(afterUnique, decls.end());
|
||||
@@ -845,8 +855,7 @@ bool Module::lookupQualified(Type type,
|
||||
if (wantLookupInAllClasses) {
|
||||
// Collect all of the visible declarations.
|
||||
SmallVector<ValueDecl *, 4> allDecls;
|
||||
forAllVisibleModules(Module::AccessPathTy(),
|
||||
[&](Module::ImportedModule import) {
|
||||
forAllVisibleModules(this, [&](Module::ImportedModule import) {
|
||||
import.second->lookupClassMember(import.first, name, allDecls);
|
||||
});
|
||||
|
||||
@@ -896,7 +905,7 @@ bool Module::lookupQualified(Type type,
|
||||
|
||||
// If we're supposed to remove shadowed/hidden declarations, do so now.
|
||||
if (options & NL_RemoveNonVisible) {
|
||||
removeShadowedDecls(decls, this, typeResolver);
|
||||
removeShadowedDecls(decls, getParentModule(), typeResolver);
|
||||
}
|
||||
|
||||
// We're done. Report success/failure.
|
||||
|
||||
@@ -610,7 +610,7 @@ static llvm::PointerUnion<ValueDecl*, Module*> lookupTopDecl(Parser &P,
|
||||
/// Find the ValueDecl given a type and a member name.
|
||||
static ValueDecl *lookupMember(Parser &P, Type Ty, Identifier Name) {
|
||||
SmallVector<ValueDecl *, 4> Lookup;
|
||||
P.SF.TU.lookupQualified(Ty, Name, NL_QualifiedDefault, nullptr, Lookup);
|
||||
P.SF.lookupQualified(Ty, Name, NL_QualifiedDefault, nullptr, Lookup);
|
||||
assert(Lookup.size() == 1);
|
||||
return Lookup[0];
|
||||
}
|
||||
|
||||
@@ -124,9 +124,8 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType(
|
||||
// Find the associated type declaration for this name.
|
||||
for (auto proto : basePA->getConformsTo()) {
|
||||
SmallVector<ValueDecl *, 2> decls;
|
||||
if (Builder.getModule().lookupQualified(proto->getDeclaredType(), name,
|
||||
NL_VisitSupertypes, nullptr,
|
||||
decls)) {
|
||||
if (DC->lookupQualified(proto->getDeclaredType(), name, NL_VisitSupertypes,
|
||||
nullptr, decls)) {
|
||||
for (auto decl : decls) {
|
||||
// Note: once we find any associated type, we have our answer, because
|
||||
// the archetype builder is supposed to ensure that all associated
|
||||
|
||||
@@ -70,8 +70,7 @@ LookupResult TypeChecker::lookupMember(Type type, Identifier name,
|
||||
}
|
||||
|
||||
// Look for the member.
|
||||
if (!dc->getParentModule()->lookupQualified(type, name, options, this,
|
||||
result.Results))
|
||||
if (!dc->lookupQualified(type, name, options, this, result.Results))
|
||||
return result;
|
||||
|
||||
return result;
|
||||
@@ -91,7 +90,7 @@ LookupTypeResult TypeChecker::lookupMemberType(Type type, Identifier name,
|
||||
// Look for members with the given name.
|
||||
SmallVector<ValueDecl *, 4> decls;
|
||||
unsigned options = NL_QualifiedDefault | NL_ProtocolMembers;
|
||||
if (!dc->getParentModule()->lookupQualified(type, name, options, this, decls))
|
||||
if (!dc->lookupQualified(type, name, options, this, decls))
|
||||
return result;
|
||||
|
||||
// Look through the declarations, keeping only the unique type declarations.
|
||||
|
||||
@@ -886,11 +886,8 @@ bool TypeChecker::coerceToType(Pattern *&P, DeclContext *dc, Type type,
|
||||
continue;
|
||||
VarDecl *prop = nullptr;
|
||||
SmallVector<ValueDecl *, 4> members;
|
||||
if (!dc->getParentModule()->lookupQualified(type,
|
||||
elt.getPropertyName(),
|
||||
NL_QualifiedDefault,
|
||||
this,
|
||||
members)) {
|
||||
if (!dc->lookupQualified(type, elt.getPropertyName(),
|
||||
NL_QualifiedDefault, this, members)) {
|
||||
diagnose(elt.getSubPattern()->getLoc(),
|
||||
diag::nominal_type_pattern_property_not_found,
|
||||
elt.getPropertyName().str(), patTy);
|
||||
|
||||
Reference in New Issue
Block a user