//===--- NameLookup.h - Swift Name Lookup Routines --------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines interfaces for performing name lookup. // //===----------------------------------------------------------------------===// #ifndef SWIFT_AST_NAME_LOOKUP_H #define SWIFT_AST_NAME_LOOKUP_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "swift/AST/Identifier.h" #include "swift/AST/Module.h" #include "swift/Basic/SourceLoc.h" namespace swift { class ASTContext; class DeclContext; class DeclName; class Expr; class LazyResolver; class TupleType; class Type; class TypeDecl; class ValueDecl; /// UnqualifiedLookupResult - One result of unqualified lookup. struct UnqualifiedLookupResult { private: ValueDecl *Base; ValueDecl *Value; public: UnqualifiedLookupResult(ValueDecl *value) : Base(nullptr), Value(value) { } UnqualifiedLookupResult(ValueDecl *base, ValueDecl *value) : Base(base), Value(value) { } ValueDecl *getValueDecl() const { return Value; } ValueDecl *getBaseDecl() const { return Base; } }; /// \brief This class implements and represents the result of performing /// unqualified lookup (i.e. lookup for a plain identifier). class UnqualifiedLookup { public: /// \brief Lookup an unqualified identifier \p Name in the context. /// /// If the current DeclContext is nested in a function body, the SourceLoc /// is used to determine which declarations in that body are visible. UnqualifiedLookup(DeclName Name, DeclContext *DC, LazyResolver *TypeResolver, bool IsKnownPrivate = false, SourceLoc Loc = SourceLoc(), bool IsTypeLookup = false, bool AllowProtocolMembers = false); SmallVector Results; /// \brief Return true if anything was found by the name lookup. bool isSuccess() const { return !Results.empty(); } /// \brief Get the result as a single type, or a null type if that fails. TypeDecl *getSingleTypeResult(); }; /// Describes the reason why a certain declaration is visible. enum class DeclVisibilityKind { /// Declaration is a local variable or type. LocalVariable, /// Declaration is a function parameter. FunctionParameter, /// Declaration is a generic parameter. GenericParameter, /// Declaration is a member of the immediately enclosing nominal decl. /// /// For example, 'Foo' is visible at (1) because of this. /// \code /// struct A { /// typealias Foo = Int /// func f() { /// // (1) /// } /// } /// \endcode MemberOfCurrentNominal, /// Declaration that is a requirement of a protocol implemented by the /// immediately enclosing nominal decl, in case the nominal decl does not /// supply a witness for this requirement. /// /// For example, 'foo' is visible at (1) because of this. /// \code /// protocol P { /// func foo() /// } /// struct A : P { /// func bar() { /// // (1) /// } /// } /// \endcode MemberOfProtocolImplementedByCurrentNominal, /// Declaration is a member of the superclass of the immediately enclosing /// nominal decl. MemberOfSuper, /// Declaration is a member of the non-immediately enclosing nominal decl. /// /// For example, 'Foo' is visible at (1) because of this. /// \code /// struct A { /// typealias Foo = Int /// struct B { /// func foo() { /// // (1) /// } /// } /// } /// \endcode MemberOfOutsideNominal, /// Declaration is visible at the top level because it is declared in this /// module or in an imported module. VisibleAtTopLevel, /// Declaration was found via \c AnyObject or \c AnyObject.Type. DynamicLookup, }; /// An abstract base class for a visitor that consumes declarations found within /// a given context. class VisibleDeclConsumer { virtual void anchor(); public: virtual ~VisibleDeclConsumer() = default; /// This method is called by findVisibleDecls() every time it finds a decl. virtual void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) = 0; }; /// A consumer that inserts found decls into an externally-owned SmallVector. class VectorDeclConsumer : public VisibleDeclConsumer { virtual void anchor() override; public: SmallVectorImpl &results; explicit VectorDeclConsumer(SmallVectorImpl &decls) : results(decls) {} virtual void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) override { results.push_back(VD); } }; /// A consumer that inserts found decls with a matching name into an /// externally-owned SmallVector. class NamedDeclConsumer : public VisibleDeclConsumer { virtual void anchor() override; public: DeclName name; SmallVectorImpl &results; NamedDeclConsumer(DeclName name, SmallVectorImpl &results) : name(name), results(results) {} virtual void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) override { if (VD->getFullName().matchesRef(name)) results.push_back(UnqualifiedLookupResult(VD)); } }; /// A consumer that filters out decls that are not accessible from a given /// DeclContext. class AccessFilteringDeclConsumer final : public VisibleDeclConsumer { const DeclContext *DC; VisibleDeclConsumer &ChainedConsumer; LazyResolver *TypeResolver; public: AccessFilteringDeclConsumer(const DeclContext *DC, VisibleDeclConsumer &consumer, LazyResolver *typeResolver) : DC(DC), ChainedConsumer(consumer), TypeResolver(typeResolver) {} void foundDecl(ValueDecl *D, DeclVisibilityKind reason) override; }; /// \brief Remove any declarations in the given set that were overridden by /// other declarations in that set. /// /// \returns true if any declarations were removed, false otherwise. bool removeOverriddenDecls(SmallVectorImpl &decls); /// \brief Remove any declarations in the given set that are shadowed by /// other declarations in that set. /// /// \param decls The set of declarations being considered. /// \param curModule The current module. /// \param typeResolver Used to resolve overload types. /// /// \returns true if any shadowed declarations were removed. bool removeShadowedDecls(SmallVectorImpl &decls, const Module *curModule, LazyResolver *typeResolver); /// Finds decls visible in the given context and feeds them to the given /// VisibleDeclConsumer. If the current DeclContext is nested in a function, /// the SourceLoc is used to determine which declarations in that function /// are visible. void lookupVisibleDecls(VisibleDeclConsumer &Consumer, const DeclContext *DC, LazyResolver *typeResolver, bool IncludeTopLevel, SourceLoc Loc = SourceLoc()); /// Finds decls visible as members of the given type and feeds them to the given /// VisibleDeclConsumer. /// /// \param CurrDC the DeclContext from which the lookup is done. void lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, Type BaseTy, const DeclContext *CurrDC, LazyResolver *typeResolver); namespace namelookup { enum class ResolutionKind { /// Lookup can match any number of decls, as long as they are all /// overloadable. /// /// If non-overloadable decls are returned, this indicates ambiguous lookup. Overloadable, /// Lookup should match a single decl. Exact, /// Lookup should match a single decl that declares a type. TypesOnly }; /// Performs a lookup into the given module and, if necessary, its /// reexports, observing proper shadowing rules. /// /// \param module The module that will contain the name. /// \param accessPath The import scope on \p module. /// \param name The name to look up. /// \param[out] decls Any found decls will be added to this vector. /// \param lookupKind Whether this lookup is qualified or unqualified. /// \param resolutionKind What sort of decl is expected. /// \param typeResolver The type resolver for decls that need to be /// type-checked. This is needed for shadowing resolution. /// \param moduleScopeContext The top-level context from which the lookup is /// being performed, for checking accessibility. This must be either a /// FileUnit or a Module. /// \param extraImports Private imports to include in this search. void lookupInModule(Module *module, Module::AccessPathTy accessPath, DeclName name, SmallVectorImpl &decls, NLKind lookupKind, ResolutionKind resolutionKind, LazyResolver *typeResolver, const DeclContext *moduleScopeContext, ArrayRef extraImports = {}); } // end namespace namelookup } // end namespace swift #endif