@@ -1900,6 +1900,12 @@ void namelookup::extractDirectlyReferencedNominalTypes(
19001900 llvm_unreachable (" Not a type containing nominal types?" );
19011901}
19021902
1903+ void namelookup::tryExtractDirectlyReferencedNominalTypes (
1904+ Type type, SmallVectorImpl<NominalTypeDecl *> &decls) {
1905+ if (!type->is <ModuleType>() && type->mayHaveMembers ())
1906+ namelookup::extractDirectlyReferencedNominalTypes (type, decls);
1907+ }
1908+
19031909bool DeclContext::lookupQualified (Type type,
19041910 DeclNameRef member,
19051911 NLOptions options,
@@ -3048,6 +3054,102 @@ swift::getDirectlyInheritedNominalTypeDecls(
30483054 return result;
30493055}
30503056
3057+ bool IsCallAsFunctionNominalRequest::evaluate (Evaluator &evaluator,
3058+ NominalTypeDecl *decl,
3059+ DeclContext *dc) const {
3060+ auto &ctx = dc->getASTContext ();
3061+
3062+ // Do a qualified lookup for `callAsFunction`. We want to ignore access, as
3063+ // that will be checked when we actually try to solve with a `callAsFunction`
3064+ // member access.
3065+ SmallVector<ValueDecl *, 4 > results;
3066+ auto opts = NL_QualifiedDefault | NL_ProtocolMembers | NL_IgnoreAccessControl;
3067+ dc->lookupQualified (decl, DeclNameRef (ctx.Id_callAsFunction ), opts, results);
3068+
3069+ return llvm::any_of (results, [](ValueDecl *decl) -> bool {
3070+ if (auto *fd = dyn_cast<FuncDecl>(decl))
3071+ return fd->isCallAsFunctionMethod ();
3072+ return false ;
3073+ });
3074+ }
3075+
3076+ bool TypeBase::isCallAsFunctionType (DeclContext *dc) {
3077+ // We can perform the lookup at module scope to allow us to better cache the
3078+ // result across different contexts. Given we'll be doing a qualified lookup,
3079+ // this shouldn't make a difference.
3080+ dc = dc->getModuleScopeContext ();
3081+
3082+ // Note this excludes AnyObject.
3083+ SmallVector<NominalTypeDecl *, 4 > decls;
3084+ tryExtractDirectlyReferencedNominalTypes (this , decls);
3085+
3086+ auto &ctx = dc->getASTContext ();
3087+ return llvm::any_of (decls, [&](auto *decl) {
3088+ IsCallAsFunctionNominalRequest req (decl, dc);
3089+ return evaluateOrDefault (ctx.evaluator , req, false );
3090+ });
3091+ }
3092+
3093+ template <class DynamicAttribute , class Req >
3094+ static bool checkForDynamicAttribute (Evaluator &eval, NominalTypeDecl *decl) {
3095+ // If this type has the attribute on it, then yes!
3096+ if (decl->getAttrs ().hasAttribute <DynamicAttribute>())
3097+ return true ;
3098+
3099+ auto hasAttribute = [&](NominalTypeDecl *decl) -> bool {
3100+ return evaluateOrDefault (eval, Req{decl}, false );
3101+ };
3102+
3103+ // Check the protocols the type conforms to.
3104+ for (auto *proto : decl->getAllProtocols ()) {
3105+ if (hasAttribute (proto))
3106+ return true ;
3107+ }
3108+
3109+ // Check the superclass if present.
3110+ if (auto *classDecl = dyn_cast<ClassDecl>(decl)) {
3111+ if (auto *superclass = classDecl->getSuperclassDecl ()) {
3112+ if (hasAttribute (superclass))
3113+ return true ;
3114+ }
3115+ }
3116+ return false ;
3117+ }
3118+
3119+ bool HasDynamicMemberLookupAttributeRequest::evaluate (
3120+ Evaluator &eval, NominalTypeDecl *decl) const {
3121+ using Req = HasDynamicMemberLookupAttributeRequest;
3122+ return checkForDynamicAttribute<DynamicMemberLookupAttr, Req>(eval, decl);
3123+ }
3124+
3125+ bool TypeBase::hasDynamicMemberLookupAttribute () {
3126+ SmallVector<NominalTypeDecl *, 4 > decls;
3127+ tryExtractDirectlyReferencedNominalTypes (this , decls);
3128+
3129+ auto &ctx = getASTContext ();
3130+ return llvm::any_of (decls, [&](auto *decl) {
3131+ HasDynamicMemberLookupAttributeRequest req (decl);
3132+ return evaluateOrDefault (ctx.evaluator , req, false );
3133+ });
3134+ }
3135+
3136+ bool HasDynamicCallableAttributeRequest::evaluate (Evaluator &eval,
3137+ NominalTypeDecl *decl) const {
3138+ using Req = HasDynamicCallableAttributeRequest;
3139+ return checkForDynamicAttribute<DynamicCallableAttr, Req>(eval, decl);
3140+ }
3141+
3142+ bool TypeBase::hasDynamicCallableAttribute () {
3143+ SmallVector<NominalTypeDecl *, 4 > decls;
3144+ tryExtractDirectlyReferencedNominalTypes (this , decls);
3145+
3146+ auto &ctx = getASTContext ();
3147+ return llvm::any_of (decls, [&](auto *decl) {
3148+ HasDynamicCallableAttributeRequest req (decl);
3149+ return evaluateOrDefault (ctx.evaluator , req, false );
3150+ });
3151+ }
3152+
30513153void FindLocalVal::checkPattern (const Pattern *Pat, DeclVisibilityKind Reason) {
30523154 Pat->forEachVariable ([&](VarDecl *VD) { checkValueDecl (VD, Reason); });
30533155}
0 commit comments