Skip to content

Commit bc0445d

Browse files
committed
Narrow a few LazyResolver::resolveDeclSignature() calls to what they really need.
Specifically, introduce entrypoints for "resolve overridden decl" and "is @objc". These can be computed cheaply in many more cases.
1 parent 2456868 commit bc0445d

File tree

9 files changed

+78
-28
lines changed

9 files changed

+78
-28
lines changed

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.

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7459,6 +7459,12 @@ GenericSignature *GenericSignatureBuilder::computeRequirementSignature(
74597459
ProtocolDecl *proto) {
74607460
GenericSignatureBuilder builder(proto->getASTContext());
74617461

7462+
if (!proto->hasInterfaceType()) {
7463+
// FIXME: Overkill.
7464+
if (auto lazyResolver = proto->getASTContext().getLazyResolver())
7465+
lazyResolver->resolveDeclSignature(proto);
7466+
}
7467+
74627468
// Add the 'self' parameter.
74637469
auto selfType =
74647470
proto->getSelfInterfaceType()->castTo<GenericTypeParamType>();

lib/AST/NameLookup.cpp

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -80,31 +80,16 @@ static void forAllVisibleModules(const DeclContext *DC, const Fn &fn) {
8080
cast<ModuleDecl>(moduleScope)->forAllVisibleModules(ModuleDecl::AccessPathTy(), fn);
8181
}
8282

83-
/// Determine whether the given declaration can be an override.
84-
static bool canBeAnOverride(ValueDecl *decl) {
85-
// Only declarations within classes can have an overridden declaration.
86-
if (!decl->getDeclContext()->getAsClassOrClassExtensionContext())
87-
return false;
88-
89-
// FIXME: We could rely on the presence of the 'override' keyword to
90-
// narrow this check.
91-
return true;
92-
}
93-
9483
bool swift::removeOverriddenDecls(SmallVectorImpl<ValueDecl*> &decls) {
9584
if (decls.size() < 2)
9685
return false;
9786

9887
auto lazyResolver = decls.front()->getASTContext().getLazyResolver();
9988
llvm::SmallPtrSet<ValueDecl*, 8> overridden;
10089
for (auto decl : decls) {
101-
// Skip anything that can't be an override.
102-
if (!canBeAnOverride(decl)) continue;
103-
10490
// Compute enough information to make the overridden-declaration available.
105-
// FIXME: Narrow this check!
10691
if (lazyResolver)
107-
lazyResolver->resolveDeclSignature(decl);
92+
lazyResolver->resolveOverriddenDecl(decl);
10893

10994
while (auto overrides = decl->getOverriddenDecl()) {
11095
overridden.insert(overrides);
@@ -120,6 +105,10 @@ bool swift::removeOverriddenDecls(SmallVectorImpl<ValueDecl*> &decls) {
120105
/// cause instead (incomplete circularity detection).
121106
assert(decl != overrides && "Circular class inheritance?");
122107
decl = overrides;
108+
109+
if (lazyResolver)
110+
lazyResolver->resolveOverriddenDecl(decl);
111+
123112
continue;
124113
}
125114

@@ -1909,17 +1898,20 @@ bool DeclContext::lookupQualified(Type type,
19091898
if ((options & NL_OnlyTypes) && !isa<TypeDecl>(decl))
19101899
continue;
19111900

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

19151908
// If the declaration has an override, name lookup will also have
19161909
// found the overridden method. Skip this declaration, because we
19171910
// prefer the overridden method.
1918-
if (decl->getOverriddenDecl())
1919-
continue;
1911+
if (typeResolver)
1912+
typeResolver->resolveOverriddenDecl(decl);
19201913

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

19251917
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: 1 addition & 1 deletion
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()) {

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/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) {

lib/Sema/TypeChecker.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,12 @@ class TypeChecker final : public LazyResolver {
13781378
validateDeclForNameLookup(VD);
13791379
}
13801380

1381+
/// Resolve the "overridden" declaration of the given declaration.
1382+
virtual void resolveOverriddenDecl(ValueDecl *VD) override;
1383+
1384+
/// Resolve the "is Objective-C" bit for the given declaration.
1385+
virtual void resolveIsObjC(ValueDecl *VD) override;
1386+
13811387
virtual void bindExtension(ExtensionDecl *ext) override;
13821388

13831389
virtual void resolveExtension(ExtensionDecl *ext) override {

0 commit comments

Comments
 (0)