Skip to content

Commit d9c0ca9

Browse files
authored
Merge pull request #16997 from DougGregor/resolve-fewer-decl-signatures
[AST] Resolve fewer decl signatures
2 parents 1ffc687 + 64b1c35 commit d9c0ca9

15 files changed

+132
-57
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class Sema;
2424

2525
namespace swift {
2626

27+
class DeclContext;
28+
2729
class ClangModuleLoader : public ModuleLoader {
2830
private:
2931
virtual void anchor();
@@ -46,6 +48,16 @@ class ClangModuleLoader : public ModuleLoader {
4648
/// \returns true if there was an error adding the search path.
4749
virtual bool addSearchPath(StringRef newSearchPath, bool isFramework,
4850
bool isSystem) = 0;
51+
52+
/// Determine whether \c overlayDC is within an overlay module for the
53+
/// imported context enclosing \c importedDC.
54+
///
55+
/// This routine is used for various hacks that are only permitted within
56+
/// overlays of imported modules, e.g., Objective-C bridging conformances.
57+
virtual bool isInOverlayModuleForImportedModule(
58+
const DeclContext *overlayDC,
59+
const DeclContext *importedDC) = 0;
60+
4961
};
5062

5163
} // namespace swift

include/swift/AST/LazyResolver.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ class LazyResolver {
6565
/// consistency and provides the value a type.
6666
virtual void resolveDeclSignature(ValueDecl *VD) = 0;
6767

68+
/// Resolve the "overridden" declaration of the given declaration.
69+
virtual void resolveOverriddenDecl(ValueDecl *VD) = 0;
70+
71+
/// Resolve the "is Objective-C" bit for the given declaration.
72+
virtual void resolveIsObjC(ValueDecl *VD) = 0;
73+
6874
/// Resolve the types in the inheritance clause of the given
6975
/// declaration context, which will be a type declaration or
7076
/// extension declaration.

include/swift/ClangImporter/ClangImporter.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,15 @@ class ClangImporter final : public ClangModuleLoader {
143143
ArrayRef<std::pair<Identifier, SourceLoc>> path)
144144
override;
145145

146+
/// Determine whether \c overlayDC is within an overlay module for the
147+
/// imported context enclosing \c importedDC.
148+
///
149+
/// This routine is used for various hacks that are only permitted within
150+
/// overlays of imported modules, e.g., Objective-C bridging conformances.
151+
bool isInOverlayModuleForImportedModule(
152+
const DeclContext *overlayDC,
153+
const DeclContext *importedDC) override;
154+
146155
/// \brief Look for declarations associated with the given name.
147156
///
148157
/// \param name The name we're searching for.
@@ -350,14 +359,6 @@ class ClangImporter final : public ClangModuleLoader {
350359
ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN,
351360
ArrayRef<clang::Module *> Exported);
352361

353-
/// Determine whether \c overlayDC is within an overlay module for the
354-
/// imported context enclosing \c importedDC.
355-
///
356-
/// This routine is used for various hacks that are only permitted within
357-
/// overlays of imported modules, e.g., Objective-C bridging conformances.
358-
bool isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
359-
const DeclContext *importedDC);
360-
361362
} // end namespace swift
362363

363364
#endif

lib/AST/ConformanceLookupTable.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,6 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
161161
SmallVector<ProtocolConformance *, 2> conformances;
162162
loader.first->loadAllConformances(nominal, loader.second, conformances);
163163
loadAllConformances(nominal, conformances);
164-
} else if (nominal->getParentSourceFile() && resolver) {
165-
resolver->resolveDeclSignature(nominal);
166164
}
167165

168166
nominalFunc(nominal);

lib/AST/Decl.cpp

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3495,19 +3495,7 @@ bool ProtocolDecl::existentialTypeSupportedSlow(LazyResolver *resolver) {
34953495
if (isObjC())
34963496
return true;
34973497

3498-
// Resolve the protocol's type.
3499-
if (resolver && !hasInterfaceType())
3500-
resolver->resolveDeclSignature(this);
3501-
35023498
for (auto member : getMembers()) {
3503-
if (auto vd = dyn_cast<ValueDecl>(member)) {
3504-
if (resolver && !vd->hasInterfaceType())
3505-
resolver->resolveDeclSignature(vd);
3506-
}
3507-
3508-
if (member->isInvalid())
3509-
continue;
3510-
35113499
// Check for associated types.
35123500
if (isa<AssociatedTypeDecl>(member)) {
35133501
// An existential type cannot be used if the protocol has an
@@ -3524,6 +3512,9 @@ bool ProtocolDecl::existentialTypeSupportedSlow(LazyResolver *resolver) {
35243512
continue;
35253513
}
35263514

3515+
if (resolver && !valueMember->hasInterfaceType())
3516+
resolver->resolveDeclSignature(valueMember);
3517+
35273518
if (!isAvailableInExistential(valueMember)) {
35283519
Bits.ProtocolDecl.ExistentialTypeSupported = false;
35293520
return false;

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7465,6 +7465,12 @@ GenericSignature *GenericSignatureBuilder::computeRequirementSignature(
74657465
ProtocolDecl *proto) {
74667466
GenericSignatureBuilder builder(proto->getASTContext());
74677467

7468+
if (!proto->hasInterfaceType()) {
7469+
// FIXME: Overkill.
7470+
if (auto lazyResolver = proto->getASTContext().getLazyResolver())
7471+
lazyResolver->resolveDeclSignature(proto);
7472+
}
7473+
74687474
// Add the 'self' parameter.
74697475
auto selfType =
74707476
proto->getSelfInterfaceType()->castTo<GenericTypeParamType>();

lib/AST/NameLookup.cpp

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "NameLookupImpl.h"
18-
#include "swift/ClangImporter/ClangImporter.h"
1918
#include "swift/AST/NameLookup.h"
2019
#include "swift/AST/ASTContext.h"
2120
#include "swift/AST/ASTScope.h"
2221
#include "swift/AST/ASTVisitor.h"
22+
#include "swift/AST/ClangModuleLoader.h"
2323
#include "swift/AST/DebuggerClient.h"
2424
#include "swift/AST/ExistentialLayout.h"
2525
#include "swift/AST/LazyResolver.h"
@@ -81,11 +81,16 @@ static void forAllVisibleModules(const DeclContext *DC, const Fn &fn) {
8181
}
8282

8383
bool swift::removeOverriddenDecls(SmallVectorImpl<ValueDecl*> &decls) {
84-
if (decls.empty())
84+
if (decls.size() < 2)
8585
return false;
8686

87+
auto lazyResolver = decls.front()->getASTContext().getLazyResolver();
8788
llvm::SmallPtrSet<ValueDecl*, 8> overridden;
8889
for (auto decl : decls) {
90+
// Compute enough information to make the overridden-declaration available.
91+
if (lazyResolver)
92+
lazyResolver->resolveOverriddenDecl(decl);
93+
8994
while (auto overrides = decl->getOverriddenDecl()) {
9095
overridden.insert(overrides);
9196

@@ -100,6 +105,10 @@ bool swift::removeOverriddenDecls(SmallVectorImpl<ValueDecl*> &decls) {
100105
/// cause instead (incomplete circularity detection).
101106
assert(decl != overrides && "Circular class inheritance?");
102107
decl = overrides;
108+
109+
if (lazyResolver)
110+
lazyResolver->resolveOverriddenDecl(decl);
111+
103112
continue;
104113
}
105114

@@ -299,13 +308,18 @@ bool swift::removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
299308
// Prefer declarations in an overlay to similar declarations in
300309
// the Clang module it customizes.
301310
if (firstDecl->hasClangNode() != secondDecl->hasClangNode()) {
302-
if (isInOverlayModuleForImportedModule(firstDecl->getDeclContext(),
303-
secondDecl->getDeclContext())){
311+
auto clangLoader = ctx.getClangModuleLoader();
312+
if (!clangLoader) continue;
313+
314+
if (clangLoader->isInOverlayModuleForImportedModule(
315+
firstDecl->getDeclContext(),
316+
secondDecl->getDeclContext())) {
304317
shadowed.insert(secondDecl);
305318
continue;
306319
}
307320

308-
if (isInOverlayModuleForImportedModule(secondDecl->getDeclContext(),
321+
if (clangLoader->isInOverlayModuleForImportedModule(
322+
secondDecl->getDeclContext(),
309323
firstDecl->getDeclContext())) {
310324
shadowed.insert(firstDecl);
311325
break;
@@ -1755,13 +1769,6 @@ bool DeclContext::lookupQualified(Type type,
17551769
// criteria.
17561770
bool onlyCompleteObjectInits = false;
17571771
auto isAcceptableDecl = [&](NominalTypeDecl *current, ValueDecl *decl) -> bool {
1758-
// If the decl is currently being type checked, then we have something
1759-
// cyclic going on. Instead of poking at parts that are potentially not
1760-
// set up, just assume it is acceptable. This will make sure we produce an
1761-
// error later.
1762-
if (!decl->hasValidSignature())
1763-
return true;
1764-
17651772
// Filter out designated initializers, if requested.
17661773
if (onlyCompleteObjectInits) {
17671774
if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
@@ -1780,8 +1787,12 @@ bool DeclContext::lookupQualified(Type type,
17801787
}
17811788

17821789
// Check access.
1783-
if (!(options & NL_IgnoreAccessControl))
1790+
if (!(options & NL_IgnoreAccessControl)) {
1791+
if (typeResolver)
1792+
typeResolver->resolveAccessControl(decl);
1793+
17841794
return decl->isAccessibleFrom(this);
1795+
}
17851796

17861797
return true;
17871798
};
@@ -1823,11 +1834,6 @@ bool DeclContext::lookupQualified(Type type,
18231834
if ((options & NL_OnlyTypes) && !isa<TypeDecl>(decl))
18241835
continue;
18251836

1826-
// Resolve the declaration signature when we find the
1827-
// declaration.
1828-
if (typeResolver)
1829-
typeResolver->resolveDeclSignature(decl);
1830-
18311837
if (isAcceptableDecl(current, decl))
18321838
decls.push_back(decl);
18331839
}
@@ -1892,17 +1898,20 @@ bool DeclContext::lookupQualified(Type type,
18921898
if ((options & NL_OnlyTypes) && !isa<TypeDecl>(decl))
18931899
continue;
18941900

1901+
// If the declaration is not @objc, it cannot be called dynamically.
18951902
if (typeResolver)
1896-
typeResolver->resolveDeclSignature(decl);
1903+
typeResolver->resolveIsObjC(decl);
1904+
1905+
if (!decl->isObjC())
1906+
continue;
18971907

18981908
// If the declaration has an override, name lookup will also have
18991909
// found the overridden method. Skip this declaration, because we
19001910
// prefer the overridden method.
1901-
if (decl->getOverriddenDecl())
1902-
continue;
1911+
if (typeResolver)
1912+
typeResolver->resolveOverriddenDecl(decl);
19031913

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

19081917
auto dc = decl->getDeclContext();

lib/AST/Type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1835,7 +1835,7 @@ getObjCObjectRepresentable(Type type, const DeclContext *dc) {
18351835
if (auto classDecl = type->getClassOrBoundGenericClass()) {
18361836
auto &ctx = classDecl->getASTContext();
18371837
if (auto resolver = ctx.getLazyResolver())
1838-
resolver->resolveDeclSignature(classDecl);
1838+
resolver->resolveIsObjC(classDecl);
18391839

18401840
if (classDecl->isObjC())
18411841
return ForeignRepresentableKind::Object;

lib/ClangImporter/ClangImporter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3539,7 +3539,7 @@ EffectiveClangContext ClangImporter::Implementation::getEffectiveClangContext(
35393539

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

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

3601-
bool swift::isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
3601+
bool ClangImporter::isInOverlayModuleForImportedModule(
3602+
const DeclContext *overlayDC,
36023603
const DeclContext *importedDC) {
36033604
overlayDC = overlayDC->getModuleScopeContext();
36043605
importedDC = importedDC->getModuleScopeContext();
@@ -3613,7 +3614,7 @@ bool swift::isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
36133614

36143615
// Is this a private module that's re-exported to the public (overlay) name?
36153616
auto clangModule =
3616-
importedClangModuleUnit->getClangModule()->getTopLevelModule();
3617+
importedClangModuleUnit->getClangModule()->getTopLevelModule();
36173618
return !clangModule->ExportAsModule.empty() &&
36183619
clangModule->ExportAsModule == overlayModule->getName().str();
36193620
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4395,9 +4395,6 @@ namespace {
43954395
T *found = nullptr;
43964396
for (auto result : results) {
43974397
if (auto singleResult = dyn_cast<T>(result)) {
4398-
if (auto typeResolver = Impl.getTypeResolver())
4399-
typeResolver->resolveDeclSignature(singleResult);
4400-
44014398
// Skip versioned variants.
44024399
const DeclAttributes &attrs = singleResult->getAttrs();
44034400
if (attrs.isUnavailableInSwiftVersion(languageVersion))

lib/ClangImporter/ImportType.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,8 +2364,6 @@ getNamedSwiftTypeSpecialization(ModuleDecl *module, StringRef name,
23642364
NLKind::UnqualifiedLookup, results);
23652365
if (results.size() == 1) {
23662366
if (auto nominalDecl = dyn_cast<NominalTypeDecl>(results.front())) {
2367-
if (auto *typeResolver = getTypeResolver())
2368-
typeResolver->resolveDeclSignature(nominalDecl);
23692367
if (auto params = nominalDecl->getGenericParams()) {
23702368
if (params->size() == args.size()) {
23712369
// When we form the bound generic type, make sure we get the

lib/Sema/TypeCheckAttr.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
#include "MiscDiagnostics.h"
1919
#include "swift/AST/GenericSignatureBuilder.h"
2020
#include "swift/AST/ASTVisitor.h"
21+
#include "swift/AST/ClangModuleLoader.h"
2122
#include "swift/AST/GenericEnvironment.h"
2223
#include "swift/AST/NameLookup.h"
2324
#include "swift/AST/ParameterList.h"
2425
#include "swift/AST/Types.h"
25-
#include "swift/ClangImporter/ClangImporter.h"
2626
#include "swift/Parse/Lexer.h"
2727
#include "llvm/Support/Debug.h"
2828

@@ -1413,7 +1413,9 @@ static bool isObjCClassExtensionInOverlay(DeclContext *dc) {
14131413
if (!classDecl)
14141414
return false;
14151415

1416-
return isInOverlayModuleForImportedModule(ext, classDecl);
1416+
auto clangLoader = dc->getASTContext().getClangModuleLoader();
1417+
if (!clangLoader) return false;
1418+
return clangLoader->isInOverlayModuleForImportedModule(ext, classDecl);
14171419
}
14181420

14191421
void AttributeChecker::visitRequiredAttr(RequiredAttr *attr) {

lib/Sema/TypeCheckDecl.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3792,6 +3792,51 @@ void TypeChecker::validateDecl(PrecedenceGroupDecl *PGD) {
37923792
if (isInvalid) PGD->setInvalid();
37933793
}
37943794

3795+
void TypeChecker::resolveOverriddenDecl(ValueDecl *VD) {
3796+
// Only members of classes can override other declarations.
3797+
if (!VD->getDeclContext()->getAsClassOrClassExtensionContext())
3798+
return;
3799+
3800+
// Types that aren't associated types cannot be overridden.
3801+
if (isa<TypeDecl>(VD) && !isa<AssociatedTypeDecl>(VD))
3802+
return;
3803+
3804+
// FIXME: We should check for the 'override' or 'required' keywords
3805+
// here, to short-circuit checking in the common case.
3806+
3807+
// FIXME: We should perform more minimal validation.
3808+
validateDeclForNameLookup(VD);
3809+
}
3810+
3811+
void TypeChecker::resolveIsObjC(ValueDecl *VD) {
3812+
// Short-circuit this operation if we already know that the entity is @objc.
3813+
if (VD->isObjC()) return;
3814+
3815+
auto dc = VD->getDeclContext();
3816+
if (dc->getAsClassOrClassExtensionContext()) {
3817+
// Members of classes can be @objc.
3818+
3819+
// FIXME: We
3820+
validateDeclForNameLookup(VD);
3821+
}
3822+
else if (isa<ClassDecl>(VD)) {
3823+
// Classes can be @objc.
3824+
3825+
// Protocols and enums can also be @objc, but this is covered by the
3826+
// isObjC() check at the beginning.
3827+
}
3828+
else if (isa<ProtocolDecl>(dc) && cast<ProtocolDecl>(dc)->isObjC()) {
3829+
// Members of @objc protocols are @objc.
3830+
}
3831+
else {
3832+
// Cannot be @objc; do nothing.
3833+
return;
3834+
}
3835+
3836+
// FIXME: Narrow this computation to just the @objc bits.
3837+
validateDeclForNameLookup(VD);
3838+
}
3839+
37953840
PrecedenceGroupDecl *TypeChecker::lookupPrecedenceGroup(DeclContext *dc,
37963841
Identifier name,
37973842
SourceLoc nameLoc) {

0 commit comments

Comments
 (0)