static bool isDeclVisibleInLookupMode(ValueDecl *Member, LookupState LS, const DeclContext *FromContext, LazyResolver *TypeResolver) { // Accessors are never visible directly in the source language. if (isa<AccessorDecl>(Member)) return false; if (TypeResolver) { TypeResolver->resolveDeclSignature(Member); } // Check access when relevant. if (!Member->getDeclContext()->isLocalContext() && !isa<GenericTypeParamDecl>(Member) && !isa<ParamDecl>(Member) && FromContext->getASTContext().LangOpts.EnableAccessControl) { if (!Member->isAccessibleFrom(FromContext)) return false; } if (auto *FD = dyn_cast<FuncDecl>(Member)) { // Cannot call static functions on non-metatypes. if (!LS.isOnMetatype() && FD->isStatic()) return false; // Otherwise, either call a function or curry it. return true; } if (auto *VD = dyn_cast<VarDecl>(Member)) { // Cannot use static properties on non-metatypes. if (!(LS.isQualified() && LS.isOnMetatype()) && VD->isStatic()) return false; // Cannot use instance properties on metatypes. if (LS.isOnMetatype() && !VD->isStatic() && !LS.isIncludingInstanceMembers()) return false; return true; } if (isa<EnumElementDecl>(Member)) { // Cannot reference enum elements on non-metatypes. if (!(LS.isQualified() && LS.isOnMetatype())) return false; } if (auto CD = dyn_cast<ConstructorDecl>(Member)) { // Constructors with stub implementations cannot be called in Swift. if (CD->hasStubImplementation()) return false; if (LS.isQualified() && LS.isOnSuperclass()) { // Cannot call initializers from a superclass, except for inherited // convenience initializers. return LS.isInheritsSuperclassInitializers() && CD->isInheritable(); } } if (isa<TypeDecl>(Member)) return areTypeDeclsVisibleInLookupMode(LS); return true; }
void swift::lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, Type BaseTy, const DeclContext *CurrDC, LazyResolver *TypeResolver, bool includeInstanceMembers) { assert(CurrDC); LookupState ls = LookupState::makeQualified(); if (includeInstanceMembers) { ls = ls.withIncludedInstanceMembers(); } ::lookupVisibleMemberDecls(BaseTy, Consumer, CurrDC, ls, DeclVisibilityKind::MemberOfCurrentNominal, TypeResolver); }
static void lookupVisibleMemberDeclsImpl( Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver, GenericSignatureBuilder *GSB, VisitedSet &Visited) { // Just look through l-valueness. It doesn't affect name lookup. assert(BaseTy && "lookup into null type"); assert(!BaseTy->hasLValueType()); // Handle metatype references, as in "some_type.some_member". These are // special and can't have extensions. if (auto MTT = BaseTy->getAs<AnyMetatypeType>()) { // The metatype represents an arbitrary named type: dig through to the // declared type to see what we're dealing with. Type Ty = MTT->getInstanceType(); LookupState subLS = LookupState::makeQualified().withOnMetatype(); if (LS.isIncludingInstanceMembers()) { subLS = subLS.withIncludedInstanceMembers(); } // Just perform normal dot lookup on the type see if we find extensions or // anything else. For example, type SomeTy.SomeMember can look up static // functions, and can even look up non-static functions as well (thus // getting the address of the member). lookupVisibleMemberDeclsImpl(Ty, Consumer, CurrDC, subLS, Reason, TypeResolver, GSB, Visited); return; } // Lookup module references, as on some_module.some_member. These are // special and can't have extensions. if (ModuleType *MT = BaseTy->getAs<ModuleType>()) { AccessFilteringDeclConsumer FilteringConsumer(CurrDC, Consumer, TypeResolver); MT->getModule()->lookupVisibleDecls(ModuleDecl::AccessPathTy(), FilteringConsumer, NLKind::QualifiedLookup); return; } // If the base is AnyObject, we are doing dynamic lookup. if (BaseTy->isAnyObject()) { doDynamicLookup(Consumer, CurrDC, LS, TypeResolver); return; } // If the base is a protocol, enumerate its members. if (ProtocolType *PT = BaseTy->getAs<ProtocolType>()) { lookupVisibleProtocolMemberDecls(BaseTy, PT, Consumer, CurrDC, LS, Reason, TypeResolver, GSB, Visited); return; } // If the base is a protocol composition, enumerate members of the protocols. if (auto PC = BaseTy->getAs<ProtocolCompositionType>()) { for (auto Member : PC->getMembers()) lookupVisibleMemberDeclsImpl(Member, Consumer, CurrDC, LS, Reason, TypeResolver, GSB, Visited); return; } // Enumerate members of archetype's requirements. if (ArchetypeType *Archetype = BaseTy->getAs<ArchetypeType>()) { for (auto Proto : Archetype->getConformsTo()) lookupVisibleProtocolMemberDecls( BaseTy, Proto->getDeclaredType(), Consumer, CurrDC, LS, getReasonForSuper(Reason), TypeResolver, GSB, Visited); if (auto superclass = Archetype->getSuperclass()) lookupVisibleMemberDeclsImpl(superclass, Consumer, CurrDC, LS, getReasonForSuper(Reason), TypeResolver, GSB, Visited); return; } // If we're looking into a type parameter and we have a generic signature // builder, use the GSB to resolve where we should look. if (BaseTy->isTypeParameter() && GSB) { auto EquivClass = GSB->resolveEquivalenceClass(BaseTy, ArchetypeResolutionKind::CompleteWellFormed); if (!EquivClass) return; if (EquivClass->concreteType) { BaseTy = EquivClass->concreteType; } else { // Conformances for (const auto &Conforms : EquivClass->conformsTo) { lookupVisibleProtocolMemberDecls( BaseTy, Conforms.first->getDeclaredType(), Consumer, CurrDC, LS, getReasonForSuper(Reason), TypeResolver, GSB, Visited); } // Superclass. if (EquivClass->superclass) { lookupVisibleMemberDeclsImpl(EquivClass->superclass, Consumer, CurrDC, LS, getReasonForSuper(Reason), TypeResolver, GSB, Visited); } return; } } llvm::SmallPtrSet<ClassDecl *, 8> Ancestors; do { NominalTypeDecl *CurNominal = BaseTy->getAnyNominal(); if (!CurNominal) break; // Look in for members of a nominal type. lookupTypeMembers(BaseTy, BaseTy, Consumer, CurrDC, LS, Reason, TypeResolver); lookupDeclsFromProtocolsBeingConformedTo(BaseTy, Consumer, LS, CurrDC, Reason, TypeResolver, Visited); // If we have a class type, look into its superclass. auto *CurClass = dyn_cast<ClassDecl>(CurNominal); if (CurClass && CurClass->hasSuperclass()) { // FIXME: This path is no substitute for an actual circularity check. // The real fix is to check that the superclass doesn't introduce a // circular reference before it's written into the AST. if (Ancestors.count(CurClass)) { break; } BaseTy = CurClass->getSuperclass(); Reason = getReasonForSuper(Reason); bool InheritsSuperclassInitializers = CurClass->inheritsSuperclassInitializers(TypeResolver); if (LS.isOnSuperclass() && !InheritsSuperclassInitializers) LS = LS.withoutInheritsSuperclassInitializers(); else if (!LS.isOnSuperclass()) { LS = LS.withOnSuperclass(); if (InheritsSuperclassInitializers) LS = LS.withInheritsSuperclassInitializers(); } } else { break; } Ancestors.insert(CurClass); } while (1); }
static bool areTypeDeclsVisibleInLookupMode(LookupState LS) { // Nested type declarations can be accessed only with unqualified lookup or // on metatypes. return !LS.isQualified() || LS.isOnMetatype(); }
static void lookupVisibleMemberDeclsImpl( Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver, VisitedSet &Visited) { // Just look through l-valueness. It doesn't affect name lookup. assert(BaseTy && "lookup into null type"); BaseTy = BaseTy->getRValueType(); // Handle metatype references, as in "some_type.some_member". These are // special and can't have extensions. if (auto MTT = BaseTy->getAs<AnyMetatypeType>()) { // The metatype represents an arbitrary named type: dig through to the // declared type to see what we're dealing with. Type Ty = MTT->getInstanceType(); // Just perform normal dot lookup on the type see if we find extensions or // anything else. For example, type SomeTy.SomeMember can look up static // functions, and can even look up non-static functions as well (thus // getting the address of the member). lookupVisibleMemberDeclsImpl(Ty, Consumer, CurrDC, LookupState::makeQualified().withOnMetatype(), Reason, TypeResolver, Visited); return; } // Lookup module references, as on some_module.some_member. These are // special and can't have extensions. if (ModuleType *MT = BaseTy->getAs<ModuleType>()) { AccessFilteringDeclConsumer FilteringConsumer(CurrDC, Consumer, TypeResolver); MT->getModule()->lookupVisibleDecls(Module::AccessPathTy(), FilteringConsumer, NLKind::QualifiedLookup); return; } // If the base is a protocol, enumerate its members. if (ProtocolType *PT = BaseTy->getAs<ProtocolType>()) { lookupVisibleProtocolMemberDecls(BaseTy, PT, Consumer, CurrDC, LS, Reason, TypeResolver, Visited); return; } // If the base is a protocol composition, enumerate members of the protocols. if (auto PC = BaseTy->getAs<ProtocolCompositionType>()) { for (auto Proto : PC->getProtocols()) lookupVisibleMemberDeclsImpl(Proto, Consumer, CurrDC, LS, Reason, TypeResolver, Visited); return; } // Enumerate members of archetype's requirements. if (ArchetypeType *Archetype = BaseTy->getAs<ArchetypeType>()) { for (auto Proto : Archetype->getConformsTo()) lookupVisibleProtocolMemberDecls( BaseTy, Proto->getDeclaredType(), Consumer, CurrDC, LS, getReasonForSuper(Reason), TypeResolver, Visited); if (auto superclass = Archetype->getSuperclass()) lookupVisibleMemberDeclsImpl(superclass, Consumer, CurrDC, LS, getReasonForSuper(Reason), TypeResolver, Visited); return; } do { NominalTypeDecl *CurNominal = BaseTy->getAnyNominal(); if (!CurNominal) break; // Look in for members of a nominal type. lookupTypeMembers(BaseTy, BaseTy, Consumer, CurrDC, LS, Reason, TypeResolver); lookupDeclsFromProtocolsBeingConformedTo(BaseTy, Consumer, LS, CurrDC, Reason, TypeResolver, Visited); // If we have a class type, look into its superclass. ClassDecl *CurClass = dyn_cast<ClassDecl>(CurNominal); if (CurClass && CurClass->hasSuperclass()) { assert(BaseTy.getPointer() != CurClass->getSuperclass().getPointer() && "type is its own superclass"); BaseTy = CurClass->getSuperclass(); Reason = getReasonForSuper(Reason); bool InheritsSuperclassInitializers = CurClass->inheritsSuperclassInitializers(TypeResolver); if (LS.isOnSuperclass() && !InheritsSuperclassInitializers) LS = LS.withoutInheritsSuperclassInitializers(); else if (!LS.isOnSuperclass()) { LS = LS.withOnSuperclass(); if (InheritsSuperclassInitializers) LS = LS.withInheritsSuperclassInitializers(); } } else { break; } } while (1); }