//===--- NameLookup.cpp - Swift Name Lookup Routines ----------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 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 implements interfaces for performing name lookup. // //===----------------------------------------------------------------------===// #include "ModuleNameLookup.h" #include "swift/Basic/SourceManager.h" #include "swift/AST/LazyResolver.h" #include "swift/AST/DebuggerClient.h" #include "swift/AST/NameLookup.h" #include "swift/AST/AST.h" #include "swift/AST/ASTVisitor.h" #include "swift/Basic/Fallthrough.h" #include "swift/Basic/STLExtras.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/TinyPtrVector.h" #define DEBUG_TYPE "Name lookup" STATISTIC(NumLazyMembers, "# of serialized member contexts"); STATISTIC(NumUnloadedLazyMembers, "# of serialized member contexts never loaded"); using namespace swift; void DebuggerClient::anchor() {} template static void forAllVisibleModules(const DeclContext *DC, const Fn &fn) { DeclContext *moduleScope = DC->getModuleScopeContext(); if (auto file = dyn_cast(moduleScope)) file->forAllVisibleModules(fn); else cast(moduleScope)->forAllVisibleModules(Module::AccessPathTy(), fn); } void swift::removeShadowedDecls(SmallVectorImpl &decls, const Module *curModule, LazyResolver *typeResolver) { // Category declarations by their signatures. llvm::SmallDenseMap, llvm::TinyPtrVector> CollidingDeclGroups; bool anyCollisions = false; for (auto decl : decls) { // Determine the signature of this declaration. // FIXME: the canonical type makes a poor signature, because we don't // canonicalize away default arguments and don't canonicalize polymorphic // types well. CanType signature; // FIXME: Egregious hack to avoid failing when there are no declared types. if (!decl->hasType() || isa(decl) || isa(decl)) { // FIXME: Pass this down instead of getting it from the ASTContext. if (typeResolver) typeResolver->resolveDeclSignature(decl); if (!decl->hasType()) continue; } signature = decl->getType()->getCanonicalType(); // If we've seen a declaration with this signature before, note it. auto &knownDecls = CollidingDeclGroups[std::make_pair(signature, decl->getName())]; if (!knownDecls.empty()) anyCollisions = true; knownDecls.push_back(decl); } // If there were no signature collisions, there is nothing to do. if (!anyCollisions) return; // Determine the set of declarations that are shadowed by other declarations. llvm::SmallPtrSet shadowed; for (auto &collidingDecls : CollidingDeclGroups) { // If only one declaration has this signature, it isn't shadowed by // anything. if (collidingDecls.second.size() == 1) continue; // Compare each declaration to every other declaration. This is // unavoidably O(n^2) in the number of declarations, but because they // all have the same signature, we expect n to remain small. for (unsigned firstIdx = 0, n = collidingDecls.second.size(); firstIdx != n; ++firstIdx) { auto firstDecl = collidingDecls.second[firstIdx]; auto firstDC = firstDecl->getDeclContext(); auto firstModule = firstDecl->getModuleContext(); for (unsigned secondIdx = firstIdx + 1; secondIdx != n; ++secondIdx) { // Determine whether one module takes precedence over another. auto secondDecl = collidingDecls.second[secondIdx]; auto secondModule = secondDecl->getModuleContext(); // If the first and second declarations are in the same module, // prefer one in the type itself vs. one in an extension. // FIXME: Should redeclaration checking prevent this from happening? if (firstModule == secondModule) { auto secondDC = secondDecl->getDeclContext(); // If both declarations are in extensions, or both are in the // type definition itself, there's nothing we can do. if (isa(firstDC) == isa(secondDC)) continue; // If the second declaration is in an extension, it is shadowed // by the first declaration. if (isa(secondDC)) { shadowed.insert(secondDecl); continue; } // If the first declaration is in an extension, it is shadowed by // the second declaration. There is no point in continuing to compare // the first declaration to others. shadowed.insert(firstDecl); break; } // Prefer declarations in the current module over those in another // module. // FIXME: This is a hack. We should query a (lazily-built, cached) // module graph to determine shadowing. if ((firstModule == curModule) == (secondModule == curModule)) continue; // If the first module is the current module, the second declaration // is shadowed by the first. if (firstModule == curModule) { shadowed.insert(secondDecl); continue; } // Otherwise, the first declaration is shadowed by the second. There is // no point in continuing to compare the first declaration to others. shadowed.insert(firstDecl); break; } } } // If none of the declarations were shadowed, we're done. if (shadowed.empty()) return; // Remove shadowed declarations from the list of declarations. decls.erase(std::remove_if(decls.begin(), decls.end(), [&](ValueDecl *vd) { return shadowed.count(vd) > 0; }), decls.end()); } struct FindLocalVal : public StmtVisitor { const SourceManager &SM; SourceLoc Loc; DeclName Name; ValueDecl *MatchingValue; FindLocalVal(const SourceManager &SM, SourceLoc Loc, DeclName Name) : SM(SM), Loc(Loc), Name(Name), MatchingValue(nullptr) {} bool IntersectsRange(SourceRange R) { return SM.rangeContainsTokenLoc(R, Loc); } void checkValueDecl(ValueDecl *D) { if (D->getFullName().matchesRef(Name)) { assert(!MatchingValue); MatchingValue = D; } } void checkPattern(const Pattern *Pat) { switch (Pat->getKind()) { case PatternKind::Tuple: for (auto &field : cast(Pat)->getFields()) checkPattern(field.getPattern()); return; case PatternKind::Paren: case PatternKind::Typed: case PatternKind::Var: return checkPattern(Pat->getSemanticsProvidingPattern()); case PatternKind::Named: return checkValueDecl(cast(Pat)->getDecl()); case PatternKind::NominalType: { for (const auto &elt : cast(Pat)->getElements()) checkPattern(elt.getSubPattern()); return; } case PatternKind::EnumElement: { auto *OP = cast(Pat); if (OP->hasSubPattern()) checkPattern(OP->getSubPattern()); return; } // Handle non-vars. case PatternKind::Isa: case PatternKind::Expr: case PatternKind::Any: return; } } void checkGenericParams(GenericParamList *Params) { if (!Params) return; for (auto P : *Params) { checkValueDecl(P.getDecl()); } } void checkSourceFile(const SourceFile &SF) { for (Decl *D : SF.Decls) { if (TopLevelCodeDecl *TLCD = dyn_cast(D)) visit(TLCD->getBody()); } } void visitBreakStmt(BreakStmt *) {} void visitContinueStmt(ContinueStmt *) {} void visitFallthroughStmt(FallthroughStmt *) {} void visitReturnStmt(ReturnStmt *) {} void visitIfStmt(IfStmt * S) { visit(S->getThenStmt()); if (S->getElseStmt()) visit(S->getElseStmt()); } void visitIfConfigStmt(IfConfigStmt * S) { // Active members are attached to the enclosing declaration, so there's no // need to walk anything within. } void visitWhileStmt(WhileStmt *S) { visit(S->getBody()); } void visitDoWhileStmt(DoWhileStmt *S) { visit(S->getBody()); } void visitForStmt(ForStmt *S) { if (!IntersectsRange(S->getSourceRange())) return; visit(S->getBody()); if (MatchingValue) return; for (Decl *D : S->getInitializerVarDecls()) { if (ValueDecl *VD = dyn_cast(D)) checkValueDecl(VD); } } void visitForEachStmt(ForEachStmt *S) { if (!IntersectsRange(S->getSourceRange())) return; visit(S->getBody()); if (MatchingValue) return; checkPattern(S->getPattern()); } void visitBraceStmt(BraceStmt *S) { // We'll want to look inside any active config blocks, even if the ranges // do not intersect. (This is to accurately model how an active config // block "shares" its enclosing scope.) if (!IntersectsRange(S->getSourceRange()) && (!S->isConfigBlock() || S->isInactiveConfigBlock())) return; for (auto elem : S->getElements()) { if (Stmt *S = elem.dyn_cast()) visit(S); } if (MatchingValue) return; for (auto elem : S->getElements()) { if (Decl *D = elem.dyn_cast()) { if (ValueDecl *VD = dyn_cast(D)) checkValueDecl(VD); } } } void visitSwitchStmt(SwitchStmt *S) { if (!IntersectsRange(S->getSourceRange())) return; for (CaseStmt *C : S->getCases()) { visit(C); } } void visitCaseStmt(CaseStmt *S) { if (!IntersectsRange(S->getSourceRange())) return; for (const auto &CLI : S->getCaseLabelItems()) { auto *P = CLI.getPattern(); if (!IntersectsRange(P->getSourceRange())) checkPattern(P); } visit(S->getBody()); } }; UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC, LazyResolver *TypeResolver, SourceLoc Loc, bool IsTypeLookup) { typedef UnqualifiedLookupResult Result; Module &M = *DC->getParentModule(); ASTContext &Ctx = M.getASTContext(); const SourceManager &SM = Ctx.SourceMgr; // Never perform local lookup for operators. if (Name.isOperator()) DC = DC->getModuleScopeContext(); // If we are inside of a method, check to see if there are any ivars in scope, // and if so, whether this is a reference to one of them. while (!DC->isModuleScopeContext()) { ValueDecl *BaseDecl = 0; ValueDecl *MetaBaseDecl = 0; GenericParamList *GenericParams = nullptr; Type ExtendedType; if (auto *AFD = dyn_cast(DC)) { // Look for local variables; normally, the parser resolves these // for us, but it can't do the right thing inside local types. // FIXME: when we can parse and typecheck the function body partially for // code completion, AFD->getBody() check can be removed. if (Loc.isValid() && AFD->getBody()) { FindLocalVal localVal(SM, Loc, Name); localVal.visit(AFD->getBody()); if (!localVal.MatchingValue) { for (Pattern *P : AFD->getBodyParamPatterns()) localVal.checkPattern(P); } if (localVal.MatchingValue) { Results.push_back(Result::getLocalDecl(localVal.MatchingValue)); return; } } if (AFD->getExtensionType()) { ExtendedType = AFD->getExtensionType(); BaseDecl = AFD->getImplicitSelfDecl(); MetaBaseDecl = ExtendedType->getAnyNominal(); DC = DC->getParent(); if (auto *FD = dyn_cast(AFD)) if (FD->isStatic()) ExtendedType = MetatypeType::get(ExtendedType, M.getASTContext()); // If we're not in the body of the function, the base declaration // is the nominal type, not 'self'. if (Loc.isValid() && AFD->getBodySourceRange().isValid() && !SM.rangeContainsTokenLoc(AFD->getBodySourceRange(), Loc)) { BaseDecl = MetaBaseDecl; } } // Look in the generic parameters after checking our local declaration. GenericParams = AFD->getGenericParams(); } else if (auto *ACE = dyn_cast(DC)) { // Look for local variables; normally, the parser resolves these // for us, but it can't do the right thing inside local types. if (Loc.isValid()) { if (auto *CE = dyn_cast(ACE)) { FindLocalVal localVal(SM, Loc, Name); localVal.visit(CE->getBody()); if (!localVal.MatchingValue) { localVal.checkPattern(CE->getParams()); } if (localVal.MatchingValue) { Results.push_back(Result::getLocalDecl(localVal.MatchingValue)); return; } } } } else if (ExtensionDecl *ED = dyn_cast(DC)) { ExtendedType = ED->getExtendedType(); BaseDecl = ExtendedType->getNominalOrBoundGenericNominal(); MetaBaseDecl = BaseDecl; } else if (NominalTypeDecl *ND = dyn_cast(DC)) { ExtendedType = ND->getDeclaredType(); BaseDecl = ND; MetaBaseDecl = BaseDecl; } else if (auto I = dyn_cast(DC)) { // In a default argument, skip immediately out of both the // initializer and the function. DC = I->getParent()->getParent(); continue; } // Check the generic parameters for something with the given name. if (GenericParams) { FindLocalVal localVal(SM, Loc, Name); localVal.checkGenericParams(GenericParams); if (localVal.MatchingValue) { Results.push_back(Result::getLocalDecl(localVal.MatchingValue)); return; } } if (BaseDecl) { if (TypeResolver) TypeResolver->resolveDeclSignature(BaseDecl); SmallVector Lookup; DC->lookupQualified(ExtendedType, Name, NL_UnqualifiedDefault, TypeResolver, Lookup); bool isMetatypeType = ExtendedType->is(); bool FoundAny = false; for (auto Result : Lookup) { // If we're looking into an instance, skip static functions. if (!isMetatypeType && isa(Result) && cast(Result)->isStatic()) continue; // Classify this declaration. FoundAny = true; // Types are local or metatype members. if (auto TD = dyn_cast(Result)) { if (isa(TD)) Results.push_back(Result::getLocalDecl(Result)); else Results.push_back(Result::getMetatypeMember(MetaBaseDecl, Result)); continue; } // Functions are either metatype members or member functions. if (auto FD = dyn_cast(Result)) { if (FD->isStatic()) { if (isMetatypeType) Results.push_back(Result::getMetatypeMember(BaseDecl, Result)); } else { Results.push_back(Result::getMemberFunction(BaseDecl, Result)); } continue; } if (isa(Result)) { Results.push_back(Result::getMetatypeMember(MetaBaseDecl, Result)); continue; } // Archetype members if (ExtendedType->is()) { Results.push_back(Result::getArchetypeMember(BaseDecl, Result)); continue; } // Existential members. if (ExtendedType->isExistentialType()) { Results.push_back(Result::getExistentialMember(BaseDecl, Result)); continue; } // Everything else is a member property. Results.push_back(Result::getMemberProperty(BaseDecl, Result)); } if (FoundAny) return; // Check the generic parameters for something with the given name. auto nominal = isMetatypeType ? ExtendedType->castTo() ->getInstanceType()->getAnyNominal() : ExtendedType->getAnyNominal(); if (nominal && nominal->getGenericParams()) { FindLocalVal localVal(SM, Loc, Name); localVal.checkGenericParams(nominal->getGenericParams()); if (localVal.MatchingValue) { Results.push_back(Result::getLocalDecl(localVal.MatchingValue)); return; } } } DC = DC->getParent(); } if (auto SF = dyn_cast(DC)) { if (Loc.isValid()) { // Look for local variables in top-level code; normally, the parser // resolves these for us, but it can't do the right thing for // local types. FindLocalVal localVal(SM, Loc, Name); localVal.checkSourceFile(*SF); if (localVal.MatchingValue) { Results.push_back(Result::getLocalDecl(localVal.MatchingValue)); return; } } } // Add private imports to the extra search list. SmallVector extraImports; if (auto FU = dyn_cast(DC)) FU->getImportedModules(extraImports, Module::ImportFilter::Private); DebuggerClient *DebugClient = M.getDebugClient(); // TODO: Does the debugger client care about compound names? if (Name.isSimpleName() && DebugClient && DebugClient->lookupOverrides(Name.getSimpleName(), DC, Loc, IsTypeLookup, Results)) return; using namespace namelookup; SmallVector CurModuleResults; auto resolutionKind = IsTypeLookup ? ResolutionKind::TypesOnly : ResolutionKind::Overloadable; lookupInModule(&M, {}, Name, CurModuleResults, NLKind::UnqualifiedLookup, resolutionKind, TypeResolver, extraImports); for (auto VD : CurModuleResults) Results.push_back(Result::getModuleMember(VD)); // If we've found something, we're done. if (!Results.empty()) return; // Look for a module with the given name. if (Name.isSimpleName(M.Name)) { Results.push_back(Result::getModuleName(&M)); return; } forAllVisibleModules(DC, [&](const Module::ImportedModule &import) -> bool { if (Name.isSimpleName(import.second->Name)) { Results.push_back(Result::getModuleName(import.second)); return false; } return true; }); if (Name.isSimpleName() && DebugClient && !Results.size()) DebugClient->lookupFallbacks(Name.getSimpleName(), DC, Loc, IsTypeLookup, Results); } Optional UnqualifiedLookup::forModuleAndName(ASTContext &C, StringRef Mod, StringRef Name) { auto foundModule = C.LoadedModules.find(Mod); if (foundModule == C.LoadedModules.end()) return Nothing; Module *m = foundModule->second; return UnqualifiedLookup(C.getIdentifier(Name), m, nullptr); } TypeDecl* UnqualifiedLookup::getSingleTypeResult() { if (Results.size() != 1 || !Results.back().hasValueDecl() || !isa(Results.back().getValueDecl())) return nullptr; return cast(Results.back().getValueDecl()); } #pragma mark Member lookup table void LazyMemberLoader::anchor() {} /// Lookup table used to store members of a nominal type (and its extensions) /// for fast retrieval. class swift::MemberLookupTable { /// The last extension that was included within the member lookup table's /// results. ExtensionDecl *LastExtensionIncluded = nullptr; /// The type of the internal lookup table. typedef llvm::DenseMap> LookupTable; /// Lookup table mapping names to the set of declarations with that name. LookupTable Lookup; public: /// Create a new member lookup table for the given nominal type. explicit MemberLookupTable(NominalTypeDecl *nominal); /// Update a lookup table with members from newly-added extensions. void updateLookupTable(NominalTypeDecl *nominal); /// \brief Add the given members to the lookup table. void addMembers(ArrayRef members); /// \brief The given extension has been extended with new members; add them /// if appropriate. void addExtensionMembers(NominalTypeDecl *nominal, ExtensionDecl *ext, ArrayRef members); /// Iterator into the lookup table. typedef LookupTable::iterator iterator; iterator begin() { return Lookup.begin(); } iterator end() { return Lookup.end(); } iterator find(DeclName name) { return Lookup.find(name); } }; MemberLookupTable::MemberLookupTable(NominalTypeDecl *nominal) { // Add the members of the nominal declaration to the table. addMembers(nominal->getMembers()); // Update the lookup table to introduce members from extensions. updateLookupTable(nominal); } void MemberLookupTable::addMembers(ArrayRef members) { for (auto member : members) { // Only value declarations matter. auto vd = dyn_cast(member); if (!vd) continue; // Unnamed entities cannot be found by name lookup. if (!vd->hasName()) continue; // Add this declaration to the lookup set under its compound name and simple // name. vd->getFullName().addToLookupTable(Lookup, vd); } } void MemberLookupTable::addExtensionMembers(NominalTypeDecl *nominal, ExtensionDecl *ext, ArrayRef members) { // We have not processed any extensions yet, so there's nothing to do. if (!LastExtensionIncluded) return; // If this extension shows up in the list of extensions not yet included // in the lookup table, there's nothing to do. for (auto notIncluded = LastExtensionIncluded->NextExtension.getPointer(); notIncluded; notIncluded = notIncluded->NextExtension.getPointer()) { if (notIncluded == ext) return; } // Add the new members to the lookup table. addMembers(members); } void MemberLookupTable::updateLookupTable(NominalTypeDecl *nominal) { // If the last extension we included is the same as the last known extension, // we're already up-to-date. if (LastExtensionIncluded == nominal->LastExtension) return; // Add members from each of the extensions that we have not yet visited. for (auto next = LastExtensionIncluded ? LastExtensionIncluded->NextExtension.getPointer() : nominal->FirstExtension; next; LastExtensionIncluded = next, next = next->NextExtension.getPointer()) { addMembers(next->getMembers()); } } template static void loadAllMembers(const T *container, LazyMemberLoader * const &resolverRef, uint64_t contextData) { if (!resolverRef) return; // Don't try to load all members re-entrant-ly. auto resolver = resolverRef; const_cast(resolverRef) = nullptr; auto members = resolver->loadAllMembers(container, contextData); const_cast(container)->setMembers(members, {}); --NumUnloadedLazyMembers; } ArrayRef NominalTypeDecl::getMembers() const { loadAllMembers(this, Resolver, ResolverContextData); return Members; } ArrayRef ExtensionDecl::getMembers() const { loadAllMembers(this, Resolver, ResolverContextData); return Members; } void NominalTypeDecl::setMembers(ArrayRef M, SourceRange B) { // If we have already constructed a lookup table and we are adding members, // add them to the lookup table. if (LookupTable && M.size() > Members.size()) { // Make sure we have the complete list of extensions. (void)getExtensions(); LookupTable->addMembers(M.slice(Members.size())); } Members = M; Braces = B; } void NominalTypeDecl::setMemberLoader(LazyMemberLoader *resolver, uint64_t contextData) { assert(!Resolver && "already have a resolver"); assert(Members.empty() && "already have members"); Resolver = resolver; ResolverContextData = contextData; ++NumLazyMembers; ++NumUnloadedLazyMembers; } void ExtensionDecl::setMemberLoader(LazyMemberLoader *resolver, uint64_t contextData) { assert(!Resolver && "already have a resolver"); assert(Members.empty() && "already have members"); Resolver = resolver; ResolverContextData = contextData; ++NumLazyMembers; ++NumUnloadedLazyMembers; } ArrayRef NominalTypeDecl::lookupDirect(DeclName name) { // Make sure we have the complete list of members (in this nominal and in all // extensions). for (auto E : getExtensions()) (void)E->getMembers(); (void)getMembers(); if (!LookupTable) { // Create the lookup table. auto &ctx = getASTContext(); void *mem = ctx.Allocate(sizeof(MemberLookupTable), alignof(MemberLookupTable)); LookupTable = new (mem) MemberLookupTable(this); // Register a cleanup with the ASTContext to call the lookup table // destructor. ctx.addCleanup([this]() { this->LookupTable->~MemberLookupTable(); }); } else { // Update the lookup table, if any new extension have come into existence. LookupTable->updateLookupTable(this); } // Look for the declarations with this name. auto known = LookupTable->find(name); if (known == LookupTable->end()) return { }; // We found something; return it. return { known->second.begin(), known->second.size() }; } bool DeclContext::lookupQualified(Type type, DeclName name, unsigned options, LazyResolver *typeResolver, SmallVectorImpl &decls) const { if (type->is()) return false; // Look through lvalue and inout types. type = type->getLValueOrInOutObjectType(); // Look through metatypes. if (auto metaTy = type->getAs()) type = metaTy->getInstanceType(); // Look through DynamicSelf. if (auto dynamicSelf = type->getAs()) type = dynamicSelf->getSelfType(); // Look for module references. if (auto moduleTy = type->getAs()) { Module *module = moduleTy->getModule(); // Perform the lookup in all imports of this module. forAllVisibleModules(this, [&](const Module::ImportedModule &import) -> bool { using namespace namelookup; if (import.second != module) return true; lookupInModule(import.second, import.first, name, decls, NLKind::QualifiedLookup, ResolutionKind::Overloadable, typeResolver); // If we're able to do an unscoped lookup, we see everything. No need // 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()); return !decls.empty(); } // The set of nominal type declarations we should (and have) visited. SmallVector stack; llvm::SmallPtrSet visited; // Handle nominal types. bool wantProtocolMembers = false; bool wantLookupInAllClasses = false; if (auto nominal = type->getAnyNominal()) { visited.insert(nominal); stack.push_back(nominal); wantProtocolMembers = (options & NL_ProtocolMembers) && !isa(nominal); // If we want dynamic lookup and we're searching in the // AnyObject protocol, note this for later. if (options & NL_DynamicLookup) { if (auto proto = dyn_cast(nominal)) { if (proto->isSpecificProtocol(KnownProtocolKind::AnyObject)) wantLookupInAllClasses = true; } } } // Handle archetypes else if (auto archetypeTy = type->getAs()) { // Look in the protocols to which the archetype conforms (always). for (auto proto : archetypeTy->getConformsTo()) if (visited.insert(proto)) stack.push_back(proto); // If requested, look into the superclasses of this archetype. if (options & NL_VisitSupertypes) { if (auto superclassTy = archetypeTy->getSuperclass()) { if (auto superclassDecl = superclassTy->getAnyNominal()) { if (visited.insert(superclassDecl)) { stack.push_back(superclassDecl); wantProtocolMembers = (options & NL_ProtocolMembers) && !isa(superclassDecl); } } } } } // Handle protocol compositions. else if (auto compositionTy = type->getAs()) { SmallVector protocols; if (compositionTy->isExistentialType(protocols)) { for (auto proto : protocols) { if (visited.insert(proto)) { stack.push_back(proto); // If we want dynamic lookup and this is the AnyObject // protocol, note this for later. if ((options & NL_DynamicLookup) && proto->isSpecificProtocol(KnownProtocolKind::AnyObject)) wantLookupInAllClasses = true; } } } } // Allow filtering of the visible declarations based on bool onlyCompleteObjectInits = false; auto isAcceptableDecl = [&](NominalTypeDecl *current, Decl *decl) -> bool { // Filter out subobject initializers, if requested. if (onlyCompleteObjectInits) { if (auto ctor = dyn_cast(decl)) { if (!ctor->isCompleteObjectInit()) return false; } else { return false; } } // Ignore stub implementations. if (auto ctor = dyn_cast(decl)) { if (ctor->hasStubImplementation()) return false; } return true; }; // Visit all of the nominal types we know about, discovering any others // we need along the way. auto &ctx = getASTContext(); llvm::DenseMap knownConformances; while (!stack.empty()) { auto current = stack.back(); stack.pop_back(); // Make sure we've resolved implicit constructors, if we need them. if (name.isSimpleName(ctx.Id_init) && typeResolver) typeResolver->resolveImplicitConstructors(current); // Look for results within the current nominal type and its extensions. bool currentIsProtocol = isa(current); for (auto decl : current->lookupDirect(name)) { // Resolve the declaration signature when we find the // declaration. if (typeResolver && !decl->hasType()) { typeResolver->resolveDeclSignature(decl); if (!decl->hasType()) continue; } if (isAcceptableDecl(current, decl)) decls.push_back(decl); } // If we're not supposed to visit our supertypes, we're done. if ((options & NL_VisitSupertypes) == 0) continue; // Visit superclass. if (auto classDecl = dyn_cast(current)) { // If we're looking for initializers, only look at the superclass if the // current class permits inheritance. Even then, only find complete // object initializers. if (name.isSimpleName(ctx.Id_init)) { if (classDecl->inheritsSuperclassInitializers(typeResolver) && !classDecl->hasClangNode()) onlyCompleteObjectInits = true; else continue; } if (auto superclassType = classDecl->getSuperclass()) if (auto superclassDecl = superclassType->getClassOrBoundGenericClass()) if (visited.insert(superclassDecl)) stack.push_back(superclassDecl); } // If we're not looking at a protocol and we don't we're not supposed to // visit the protocols that this type conforms to, skip the next step. if (!wantProtocolMembers && !currentIsProtocol) continue; // Local function object used to add protocols to the stack. auto addProtocols = [&](ArrayRef protocols) { for (auto proto : protocols) { if (visited.insert(proto)) { stack.push_back(proto); } } }; // Add protocols from the current type. addProtocols(current->getProtocols()); // Add protocols from the extensions of the current type. for (auto ext : current->getExtensions()) { addProtocols(ext->getProtocols()); } } // If we want to perform lookup into all classes, do so now. if (wantLookupInAllClasses) { // Collect all of the visible declarations. SmallVector allDecls; forAllVisibleModules(this, [&](Module::ImportedModule import) { import.second->lookupClassMember(import.first, name, allDecls); }); // For each declaration whose context is not something we've // already visited above, add it to the list of declarations. llvm::SmallPtrSet knownDecls; for (auto decl : allDecls) { // If the declaration has an override, name lookup will also have // found the overridden method. Skip this declaration, because we // prefer the overridden method. if (decl->getOverriddenDecl()) continue; auto dc = decl->getDeclContext(); auto nominal = dyn_cast(dc); if (!nominal) { auto ext = cast(dc); nominal = ext->getExtendedType()->getAnyNominal(); assert(nominal && "Couldn't find nominal type?"); } // If we didn't visit this nominal type above, add this // declaration to the list. if (!visited.count(nominal) && knownDecls.insert(decl)) decls.push_back(decl); } } // If we're supposed to remove overridden declarations, do so now. if (options & NL_RemoveOverridden) { // Find all of the overridden declarations. llvm::SmallPtrSet overridden; for (auto decl : decls) { while (auto overrides = decl->getOverriddenDecl()) { overridden.insert(overrides); // Because initializers from Objective-C base classes have greater // visibility than initializers written in Swift classes, we can // have a "break" in the set of declarations we found, where // C.init overrides B.init overrides A.init, but only C.init and // A.init are in the chain. Make sure we still remove A.init from the // set in this case. if (name.isSimpleName(ctx.Id_init)) { decl = overrides; continue; } break; } } // If any methods were overridden, remove them from the results. if (!overridden.empty()) { decls.erase(std::remove_if(decls.begin(), decls.end(), [&](ValueDecl *decl) -> bool { return overridden.count(decl); }), decls.end()); } } // If we're supposed to remove shadowed/hidden declarations, do so now. if (options & NL_RemoveNonVisible) { removeShadowedDecls(decls, getParentModule(), typeResolver); } // We're done. Report success/failure. return !decls.empty(); } void ExtensionDecl::setMembers(ArrayRef M, SourceRange B) { // If this is a resolved extension and we're adding members to it, // we may have to update the extended type's lookup table. if (NextExtension.getInt() && M.size() > Members.size()) { auto nominal = getExtendedType()->getAnyNominal(); if (nominal->LookupTable) { // Make sure we have the complete list of extensions. (void)nominal->getExtensions(); nominal->LookupTable->addExtensionMembers(nominal, this, M.slice(Members.size())); } } Members = M; Braces = B; }