Skip to content

[AST] Resolve fewer decl signatures #16997

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions include/swift/AST/ClangModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class Sema;

namespace swift {

class DeclContext;

class ClangModuleLoader : public ModuleLoader {
private:
virtual void anchor();
Expand All @@ -46,6 +48,16 @@ class ClangModuleLoader : public ModuleLoader {
/// \returns true if there was an error adding the search path.
virtual bool addSearchPath(StringRef newSearchPath, bool isFramework,
bool isSystem) = 0;

/// Determine whether \c overlayDC is within an overlay module for the
/// imported context enclosing \c importedDC.
///
/// This routine is used for various hacks that are only permitted within
/// overlays of imported modules, e.g., Objective-C bridging conformances.
virtual bool isInOverlayModuleForImportedModule(
const DeclContext *overlayDC,
const DeclContext *importedDC) = 0;

};

} // namespace swift
Expand Down
6 changes: 6 additions & 0 deletions include/swift/AST/LazyResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ class LazyResolver {
/// consistency and provides the value a type.
virtual void resolveDeclSignature(ValueDecl *VD) = 0;

/// Resolve the "overridden" declaration of the given declaration.
virtual void resolveOverriddenDecl(ValueDecl *VD) = 0;

/// Resolve the "is Objective-C" bit for the given declaration.
virtual void resolveIsObjC(ValueDecl *VD) = 0;

/// Resolve the types in the inheritance clause of the given
/// declaration context, which will be a type declaration or
/// extension declaration.
Expand Down
17 changes: 9 additions & 8 deletions include/swift/ClangImporter/ClangImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,15 @@ class ClangImporter final : public ClangModuleLoader {
ArrayRef<std::pair<Identifier, SourceLoc>> path)
override;

/// Determine whether \c overlayDC is within an overlay module for the
/// imported context enclosing \c importedDC.
///
/// This routine is used for various hacks that are only permitted within
/// overlays of imported modules, e.g., Objective-C bridging conformances.
bool isInOverlayModuleForImportedModule(
const DeclContext *overlayDC,
const DeclContext *importedDC) override;

/// \brief Look for declarations associated with the given name.
///
/// \param name The name we're searching for.
Expand Down Expand Up @@ -350,14 +359,6 @@ class ClangImporter final : public ClangModuleLoader {
ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN,
ArrayRef<clang::Module *> Exported);

/// Determine whether \c overlayDC is within an overlay module for the
/// imported context enclosing \c importedDC.
///
/// This routine is used for various hacks that are only permitted within
/// overlays of imported modules, e.g., Objective-C bridging conformances.
bool isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
const DeclContext *importedDC);

} // end namespace swift

#endif
2 changes: 0 additions & 2 deletions lib/AST/ConformanceLookupTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,6 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
SmallVector<ProtocolConformance *, 2> conformances;
loader.first->loadAllConformances(nominal, loader.second, conformances);
loadAllConformances(nominal, conformances);
} else if (nominal->getParentSourceFile() && resolver) {
resolver->resolveDeclSignature(nominal);
}

nominalFunc(nominal);
Expand Down
15 changes: 3 additions & 12 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3495,19 +3495,7 @@ bool ProtocolDecl::existentialTypeSupportedSlow(LazyResolver *resolver) {
if (isObjC())
return true;

// Resolve the protocol's type.
if (resolver && !hasInterfaceType())
resolver->resolveDeclSignature(this);

for (auto member : getMembers()) {
if (auto vd = dyn_cast<ValueDecl>(member)) {
if (resolver && !vd->hasInterfaceType())
resolver->resolveDeclSignature(vd);
}

if (member->isInvalid())
continue;

// Check for associated types.
if (isa<AssociatedTypeDecl>(member)) {
// An existential type cannot be used if the protocol has an
Expand All @@ -3524,6 +3512,9 @@ bool ProtocolDecl::existentialTypeSupportedSlow(LazyResolver *resolver) {
continue;
}

if (resolver && !valueMember->hasInterfaceType())
resolver->resolveDeclSignature(valueMember);

if (!isAvailableInExistential(valueMember)) {
Bits.ProtocolDecl.ExistentialTypeSupported = false;
return false;
Expand Down
6 changes: 6 additions & 0 deletions lib/AST/GenericSignatureBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7459,6 +7459,12 @@ GenericSignature *GenericSignatureBuilder::computeRequirementSignature(
ProtocolDecl *proto) {
GenericSignatureBuilder builder(proto->getASTContext());

if (!proto->hasInterfaceType()) {
// FIXME: Overkill.
if (auto lazyResolver = proto->getASTContext().getLazyResolver())
lazyResolver->resolveDeclSignature(proto);
}

// Add the 'self' parameter.
auto selfType =
proto->getSelfInterfaceType()->castTo<GenericTypeParamType>();
Expand Down
55 changes: 32 additions & 23 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
//===----------------------------------------------------------------------===//

#include "NameLookupImpl.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTScope.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/DebuggerClient.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/LazyResolver.h"
Expand Down Expand Up @@ -81,11 +81,16 @@ static void forAllVisibleModules(const DeclContext *DC, const Fn &fn) {
}

bool swift::removeOverriddenDecls(SmallVectorImpl<ValueDecl*> &decls) {
if (decls.empty())
if (decls.size() < 2)
return false;

auto lazyResolver = decls.front()->getASTContext().getLazyResolver();
llvm::SmallPtrSet<ValueDecl*, 8> overridden;
for (auto decl : decls) {
// Compute enough information to make the overridden-declaration available.
if (lazyResolver)
lazyResolver->resolveOverriddenDecl(decl);

while (auto overrides = decl->getOverriddenDecl()) {
overridden.insert(overrides);

Expand All @@ -100,6 +105,10 @@ bool swift::removeOverriddenDecls(SmallVectorImpl<ValueDecl*> &decls) {
/// cause instead (incomplete circularity detection).
assert(decl != overrides && "Circular class inheritance?");
decl = overrides;

if (lazyResolver)
lazyResolver->resolveOverriddenDecl(decl);

continue;
}

Expand Down Expand Up @@ -299,13 +308,18 @@ bool swift::removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
// Prefer declarations in an overlay to similar declarations in
// the Clang module it customizes.
if (firstDecl->hasClangNode() != secondDecl->hasClangNode()) {
if (isInOverlayModuleForImportedModule(firstDecl->getDeclContext(),
secondDecl->getDeclContext())){
auto clangLoader = ctx.getClangModuleLoader();
if (!clangLoader) continue;

if (clangLoader->isInOverlayModuleForImportedModule(
firstDecl->getDeclContext(),
secondDecl->getDeclContext())) {
shadowed.insert(secondDecl);
continue;
}

if (isInOverlayModuleForImportedModule(secondDecl->getDeclContext(),
if (clangLoader->isInOverlayModuleForImportedModule(
secondDecl->getDeclContext(),
firstDecl->getDeclContext())) {
shadowed.insert(firstDecl);
break;
Expand Down Expand Up @@ -1755,13 +1769,6 @@ bool DeclContext::lookupQualified(Type type,
// criteria.
bool onlyCompleteObjectInits = false;
auto isAcceptableDecl = [&](NominalTypeDecl *current, ValueDecl *decl) -> bool {
// If the decl is currently being type checked, then we have something
// cyclic going on. Instead of poking at parts that are potentially not
// set up, just assume it is acceptable. This will make sure we produce an
// error later.
if (!decl->hasValidSignature())
return true;

// Filter out designated initializers, if requested.
if (onlyCompleteObjectInits) {
if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
Expand All @@ -1780,8 +1787,12 @@ bool DeclContext::lookupQualified(Type type,
}

// Check access.
if (!(options & NL_IgnoreAccessControl))
if (!(options & NL_IgnoreAccessControl)) {
if (typeResolver)
typeResolver->resolveAccessControl(decl);

return decl->isAccessibleFrom(this);
}

return true;
};
Expand Down Expand Up @@ -1823,11 +1834,6 @@ bool DeclContext::lookupQualified(Type type,
if ((options & NL_OnlyTypes) && !isa<TypeDecl>(decl))
continue;

// Resolve the declaration signature when we find the
// declaration.
if (typeResolver)
typeResolver->resolveDeclSignature(decl);

if (isAcceptableDecl(current, decl))
decls.push_back(decl);
}
Expand Down Expand Up @@ -1892,17 +1898,20 @@ bool DeclContext::lookupQualified(Type type,
if ((options & NL_OnlyTypes) && !isa<TypeDecl>(decl))
continue;

// If the declaration is not @objc, it cannot be called dynamically.
if (typeResolver)
typeResolver->resolveDeclSignature(decl);
typeResolver->resolveIsObjC(decl);

if (!decl->isObjC())
continue;

// 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;
if (typeResolver)
typeResolver->resolveOverriddenDecl(decl);

// If the declaration is not @objc, it cannot be called dynamically.
if (!decl->isObjC())
if (decl->getOverriddenDecl())
continue;

auto dc = decl->getDeclContext();
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1835,7 +1835,7 @@ getObjCObjectRepresentable(Type type, const DeclContext *dc) {
if (auto classDecl = type->getClassOrBoundGenericClass()) {
auto &ctx = classDecl->getASTContext();
if (auto resolver = ctx.getLazyResolver())
resolver->resolveDeclSignature(classDecl);
resolver->resolveIsObjC(classDecl);

if (classDecl->isObjC())
return ForeignRepresentableKind::Object;
Expand Down
7 changes: 4 additions & 3 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3539,7 +3539,7 @@ EffectiveClangContext ClangImporter::Implementation::getEffectiveClangContext(

// Resolve the type.
if (auto typeResolver = getTypeResolver())
typeResolver->resolveDeclSignature(const_cast<NominalTypeDecl *>(nominal));
typeResolver->resolveIsObjC(const_cast<NominalTypeDecl *>(nominal));

// If it's an @objc entity, go look for it.
if (nominal->isObjC()) {
Expand Down Expand Up @@ -3598,7 +3598,8 @@ importName(const clang::NamedDecl *D,
getDeclName();
}

bool swift::isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
bool ClangImporter::isInOverlayModuleForImportedModule(
const DeclContext *overlayDC,
const DeclContext *importedDC) {
overlayDC = overlayDC->getModuleScopeContext();
importedDC = importedDC->getModuleScopeContext();
Expand All @@ -3613,7 +3614,7 @@ bool swift::isInOverlayModuleForImportedModule(const DeclContext *overlayDC,

// Is this a private module that's re-exported to the public (overlay) name?
auto clangModule =
importedClangModuleUnit->getClangModule()->getTopLevelModule();
importedClangModuleUnit->getClangModule()->getTopLevelModule();
return !clangModule->ExportAsModule.empty() &&
clangModule->ExportAsModule == overlayModule->getName().str();
}
3 changes: 0 additions & 3 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4395,9 +4395,6 @@ namespace {
T *found = nullptr;
for (auto result : results) {
if (auto singleResult = dyn_cast<T>(result)) {
if (auto typeResolver = Impl.getTypeResolver())
typeResolver->resolveDeclSignature(singleResult);

// Skip versioned variants.
const DeclAttributes &attrs = singleResult->getAttrs();
if (attrs.isUnavailableInSwiftVersion(languageVersion))
Expand Down
2 changes: 0 additions & 2 deletions lib/ClangImporter/ImportType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2364,8 +2364,6 @@ getNamedSwiftTypeSpecialization(ModuleDecl *module, StringRef name,
NLKind::UnqualifiedLookup, results);
if (results.size() == 1) {
if (auto nominalDecl = dyn_cast<NominalTypeDecl>(results.front())) {
if (auto *typeResolver = getTypeResolver())
typeResolver->resolveDeclSignature(nominalDecl);
if (auto params = nominalDecl->getGenericParams()) {
if (params->size() == args.size()) {
// When we form the bound generic type, make sure we get the
Expand Down
6 changes: 4 additions & 2 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
#include "MiscDiagnostics.h"
#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Types.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/Parse/Lexer.h"
#include "llvm/Support/Debug.h"

Expand Down Expand Up @@ -1413,7 +1413,9 @@ static bool isObjCClassExtensionInOverlay(DeclContext *dc) {
if (!classDecl)
return false;

return isInOverlayModuleForImportedModule(ext, classDecl);
auto clangLoader = dc->getASTContext().getClangModuleLoader();
if (!clangLoader) return false;
return clangLoader->isInOverlayModuleForImportedModule(ext, classDecl);
}

void AttributeChecker::visitRequiredAttr(RequiredAttr *attr) {
Expand Down
45 changes: 45 additions & 0 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3792,6 +3792,51 @@ void TypeChecker::validateDecl(PrecedenceGroupDecl *PGD) {
if (isInvalid) PGD->setInvalid();
}

void TypeChecker::resolveOverriddenDecl(ValueDecl *VD) {
// Only members of classes can override other declarations.
if (!VD->getDeclContext()->getAsClassOrClassExtensionContext())
return;

// Types that aren't associated types cannot be overridden.
if (isa<TypeDecl>(VD) && !isa<AssociatedTypeDecl>(VD))
return;

// FIXME: We should check for the 'override' or 'required' keywords
// here, to short-circuit checking in the common case.

// FIXME: We should perform more minimal validation.
validateDeclForNameLookup(VD);
}

void TypeChecker::resolveIsObjC(ValueDecl *VD) {
// Short-circuit this operation if we already know that the entity is @objc.
if (VD->isObjC()) return;

auto dc = VD->getDeclContext();
if (dc->getAsClassOrClassExtensionContext()) {
// Members of classes can be @objc.

// FIXME: We
validateDeclForNameLookup(VD);
}
else if (isa<ClassDecl>(VD)) {
// Classes can be @objc.

// Protocols and enums can also be @objc, but this is covered by the
// isObjC() check at the beginning.
}
else if (isa<ProtocolDecl>(dc) && cast<ProtocolDecl>(dc)->isObjC()) {
// Members of @objc protocols are @objc.
}
else {
// Cannot be @objc; do nothing.
return;
}

// FIXME: Narrow this computation to just the @objc bits.
validateDeclForNameLookup(VD);
}

PrecedenceGroupDecl *TypeChecker::lookupPrecedenceGroup(DeclContext *dc,
Identifier name,
SourceLoc nameLoc) {
Expand Down
Loading