mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Make sure that the dynamic lookup table has the right set of members.
Clean up the "can be accessed by dynamic lookup" predicate so that it checks for a generic context. We no longer need to do the checking in name lookup, since this means that the dynamic lookup table won't have anything we can't use (thanks Jordan!). Drop the [objc] allowance for members of a generic context: it still leaves us with a very weird case of messaging something when we can't even figure out the type that we think the object has. Extend the walk searching for members to include inner classes within structs, so we get all of the members globally. Swift SVN r7799
This commit is contained in:
@@ -1072,16 +1072,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this decl can be found by id-style dynamic lookup.
|
/// Returns true if this decl can be found by id-style dynamic lookup.
|
||||||
///
|
bool canBeAccessedByDynamicLookup() const;
|
||||||
/// Note that this method does NOT check that this value is actually a class
|
|
||||||
/// member.
|
|
||||||
bool canBeAccessedByDynamicLookup() const {
|
|
||||||
if (getName().empty())
|
|
||||||
return false;
|
|
||||||
if (isa<FuncDecl>(this) || isa<VarDecl>(this) || isa<SubscriptDecl>(this))
|
|
||||||
return isInstanceMember();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determine the default argument kind and type for the given argument index
|
/// Determine the default argument kind and type for the given argument index
|
||||||
/// in this declaration, which must be a function or constructor.
|
/// in this declaration, which must be a function or constructor.
|
||||||
|
|||||||
@@ -150,7 +150,11 @@ public:
|
|||||||
|
|
||||||
/// Returns the module context that contains this context.
|
/// Returns the module context that contains this context.
|
||||||
Module *getParentModule() const;
|
Module *getParentModule() const;
|
||||||
|
|
||||||
|
/// Determine whether this declaration context is generic, meaning that it or
|
||||||
|
/// any of its parents have generic parameters.
|
||||||
|
bool isGenericContext() const;
|
||||||
|
|
||||||
/// getASTContext - Return the ASTContext for a specified DeclContext by
|
/// getASTContext - Return the ASTContext for a specified DeclContext by
|
||||||
/// walking up to the enclosing module and returning its ASTContext.
|
/// walking up to the enclosing module and returning its ASTContext.
|
||||||
ASTContext &getASTContext();
|
ASTContext &getASTContext();
|
||||||
|
|||||||
@@ -140,6 +140,42 @@ Module *DeclContext::getParentModule() const {
|
|||||||
return const_cast<Module *>(cast<Module>(DC));
|
return const_cast<Module *>(cast<Module>(DC));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine whether the given context is generic at any level.
|
||||||
|
bool DeclContext::isGenericContext() const {
|
||||||
|
for (const DeclContext *dc = this; ; dc = dc->getParent() ) {
|
||||||
|
switch (dc->getContextKind()) {
|
||||||
|
case DeclContextKind::BuiltinModule:
|
||||||
|
case DeclContextKind::ClangModule:
|
||||||
|
case DeclContextKind::SerializedModule:
|
||||||
|
case DeclContextKind::TranslationUnit:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case DeclContextKind::CapturingExpr:
|
||||||
|
if (auto funcExpr = dyn_cast<FuncExpr>(dc)) {
|
||||||
|
if (auto func = funcExpr->getDecl())
|
||||||
|
if (func->getGenericParams())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeclContextKind::ConstructorDecl:
|
||||||
|
if (cast<ConstructorDecl>(dc)->getGenericParams())
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeclContextKind::DestructorDecl:
|
||||||
|
case DeclContextKind::TopLevelCodeDecl:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DeclContextKind::ExtensionDecl:
|
||||||
|
case DeclContextKind::NominalTypeDecl:
|
||||||
|
if (dc->getDeclaredTypeOfContext()->getAnyNominal()->getGenericParams())
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only allow allocation of Decls using the allocator in ASTContext.
|
// Only allow allocation of Decls using the allocator in ASTContext.
|
||||||
void *Decl::operator new(size_t Bytes, ASTContext &C,
|
void *Decl::operator new(size_t Bytes, ASTContext &C,
|
||||||
unsigned Alignment) {
|
unsigned Alignment) {
|
||||||
@@ -446,6 +482,26 @@ ValueDecl *ValueDecl::getOverriddenDecl() const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ValueDecl::canBeAccessedByDynamicLookup() const {
|
||||||
|
if (getName().empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Dynamic lookup can only find class and protocol members.
|
||||||
|
auto dc = getDeclContext();
|
||||||
|
if (!isa<ClassDecl>(dc) && !isa<ProtocolDecl>(dc))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Dynamic lookup cannot find results within a generic context, because there
|
||||||
|
// is no sensible way to infer the generic arguments.
|
||||||
|
if (getDeclContext()->isGenericContext())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (isa<FuncDecl>(this) || isa<VarDecl>(this) || isa<SubscriptDecl>(this))
|
||||||
|
return isInstanceMember();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Type TypeDecl::getDeclaredType() const {
|
Type TypeDecl::getDeclaredType() const {
|
||||||
if (auto TAD = dyn_cast<TypeAliasDecl>(this))
|
if (auto TAD = dyn_cast<TypeAliasDecl>(this))
|
||||||
return TAD->getAliasType();
|
return TAD->getAliasType();
|
||||||
|
|||||||
@@ -152,14 +152,9 @@ void TUModuleCache::doPopulateCache(ArrayRef<Decl*> decls, bool onlyOperators) {
|
|||||||
void TUModuleCache::populateMemberCache(const TranslationUnit &TU) {
|
void TUModuleCache::populateMemberCache(const TranslationUnit &TU) {
|
||||||
for (const Decl *D : TU.Decls) {
|
for (const Decl *D : TU.Decls) {
|
||||||
if (const NominalTypeDecl *NTD = dyn_cast<NominalTypeDecl>(D)) {
|
if (const NominalTypeDecl *NTD = dyn_cast<NominalTypeDecl>(D)) {
|
||||||
if (isa<ClassDecl>(NTD) || isa<ProtocolDecl>(NTD))
|
addToMemberCache(NTD->getMembers());
|
||||||
addToMemberCache(NTD->getMembers());
|
|
||||||
} else if (const ExtensionDecl *ED = dyn_cast<ExtensionDecl>(D)) {
|
} else if (const ExtensionDecl *ED = dyn_cast<ExtensionDecl>(D)) {
|
||||||
Type baseTy = ED->getExtendedType();
|
addToMemberCache(ED->getMembers());
|
||||||
assert(baseTy && "cannot use this before type-checking");
|
|
||||||
if (auto baseNominal = baseTy->getAnyNominal())
|
|
||||||
if (isa<ClassDecl>(baseNominal) || isa<ProtocolDecl>(baseNominal))
|
|
||||||
addToMemberCache(ED->getMembers());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,9 +168,7 @@ void TUModuleCache::addToMemberCache(ArrayRef<Decl*> decls) {
|
|||||||
if (auto NTD = dyn_cast<NominalTypeDecl>(VD)) {
|
if (auto NTD = dyn_cast<NominalTypeDecl>(VD)) {
|
||||||
assert(!VD->canBeAccessedByDynamicLookup() &&
|
assert(!VD->canBeAccessedByDynamicLookup() &&
|
||||||
"inner types cannot be accessed by dynamic lookup");
|
"inner types cannot be accessed by dynamic lookup");
|
||||||
if (isa<ClassDecl>(NTD) || isa<ProtocolDecl>(NTD))
|
addToMemberCache(NTD->getMembers());
|
||||||
addToMemberCache(NTD->getMembers());
|
|
||||||
|
|
||||||
} else if (VD->canBeAccessedByDynamicLookup()) {
|
} else if (VD->canBeAccessedByDynamicLookup()) {
|
||||||
ClassMembers[VD->getName()].push_back(VD);
|
ClassMembers[VD->getName()].push_back(VD);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -690,42 +690,6 @@ ArrayRef<ValueDecl *> NominalTypeDecl::lookupDirect(Identifier name) {
|
|||||||
return { known->second.begin(), known->second.size() };
|
return { known->second.begin(), known->second.size() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether the given context is generic at any level.
|
|
||||||
static bool isGenericContext(DeclContext *dc) {
|
|
||||||
for (; ; dc = dc->getParent() ) {
|
|
||||||
switch (dc->getContextKind()) {
|
|
||||||
case DeclContextKind::BuiltinModule:
|
|
||||||
case DeclContextKind::ClangModule:
|
|
||||||
case DeclContextKind::SerializedModule:
|
|
||||||
case DeclContextKind::TranslationUnit:
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case DeclContextKind::CapturingExpr:
|
|
||||||
if (auto funcExpr = dyn_cast<FuncExpr>(dc)) {
|
|
||||||
if (auto func = funcExpr->getDecl())
|
|
||||||
if (func->getGenericParams())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeclContextKind::ConstructorDecl:
|
|
||||||
if (cast<ConstructorDecl>(dc)->getGenericParams())
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeclContextKind::DestructorDecl:
|
|
||||||
case DeclContextKind::TopLevelCodeDecl:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeclContextKind::ExtensionDecl:
|
|
||||||
case DeclContextKind::NominalTypeDecl:
|
|
||||||
if (dc->getDeclaredTypeOfContext()->getAnyNominal()->getGenericParams())
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Module::lookupQualified(Type type,
|
bool Module::lookupQualified(Type type,
|
||||||
Identifier name,
|
Identifier name,
|
||||||
unsigned options,
|
unsigned options,
|
||||||
@@ -903,11 +867,6 @@ bool Module::lookupQualified(Type type,
|
|||||||
assert(nominal && "Couldn't find nominal type?");
|
assert(nominal && "Couldn't find nominal type?");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic lookup cannot find non-Objective C results within
|
|
||||||
// a generic context.
|
|
||||||
if (!decl->isObjC() && isGenericContext(dc))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If we didn't visit this nominal type above, add this
|
// If we didn't visit this nominal type above, add this
|
||||||
// declaration to the list.
|
// declaration to the list.
|
||||||
if (!visited.count(nominal))
|
if (!visited.count(nominal))
|
||||||
|
|||||||
Reference in New Issue
Block a user