Skip to content

Commit a3063cc

Browse files
authored
[PrintAsObjC] Use TypeDeclFinder instead of custom TypeVisitor (#27189)
This is the same type-walking logic we use for access control checking, so it had better be correct. Perfect case for DRY! No functionality change.
1 parent c3db367 commit a3063cc

File tree

1 file changed

+19
-82
lines changed

1 file changed

+19
-82
lines changed

lib/PrintAsObjC/ModuleContentsWriter.cpp

Lines changed: 19 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include "swift/AST/Module.h"
1919
#include "swift/AST/ProtocolConformance.h"
2020
#include "swift/AST/SwiftNameTranslation.h"
21-
#include "swift/AST/TypeVisitor.h"
21+
#include "swift/AST/TypeDeclFinder.h"
2222
#include "swift/ClangImporter/ClangImporter.h"
2323

2424
#include "clang/AST/Decl.h"
@@ -39,92 +39,29 @@ static bool isOSObjectType(const clang::Decl *decl) {
3939
}
4040

4141
namespace {
42-
class ReferencedTypeFinder : public TypeVisitor<ReferencedTypeFinder> {
43-
friend TypeVisitor;
42+
class ReferencedTypeFinder : public TypeDeclFinder {
43+
friend TypeDeclFinder;
4444

45-
ModuleDecl &M;
4645
llvm::function_ref<void(ReferencedTypeFinder &, const TypeDecl *)> Callback;
4746
bool NeedsDefinition = false;
4847

49-
ReferencedTypeFinder(ModuleDecl &mod, decltype(Callback) callback)
50-
: M(mod), Callback(callback) {}
48+
explicit ReferencedTypeFinder(decltype(Callback) callback)
49+
: Callback(callback) {}
5150

52-
void visitType(TypeBase *base) {
53-
llvm_unreachable("unhandled type");
51+
Action visitNominalType(NominalType *nominal) override {
52+
Callback(*this, nominal->getDecl());
53+
return Action::SkipChildren;
5454
}
5555

56-
void visitTypeAliasType(TypeAliasType *aliasTy) {
56+
Action visitTypeAliasType(TypeAliasType *aliasTy) override {
5757
if (aliasTy->getDecl()->hasClangNode() &&
5858
!aliasTy->getDecl()->isCompatibilityAlias()) {
59+
assert(!aliasTy->getGenericSignature());
5960
Callback(*this, aliasTy->getDecl());
6061
} else {
61-
visit(aliasTy->getSinglyDesugaredType());
62+
Type(aliasTy->getSinglyDesugaredType()).walk(*this);
6263
}
63-
}
64-
65-
void visitParenType(ParenType *parenTy) {
66-
visit(parenTy->getSinglyDesugaredType());
67-
}
68-
69-
void visitTupleType(TupleType *tupleTy) {
70-
for (auto elemTy : tupleTy->getElementTypes())
71-
visit(elemTy);
72-
}
73-
74-
void visitReferenceStorageType(ReferenceStorageType *ty) {
75-
visit(ty->getReferentType());
76-
}
77-
78-
void visitNominalType(NominalType *nominal) {
79-
Callback(*this, nominal->getDecl());
80-
}
81-
82-
void visitAnyMetatypeType(AnyMetatypeType *metatype) {
83-
visit(metatype->getInstanceType());
84-
}
85-
86-
void visitDynamicSelfType(DynamicSelfType *module) {
87-
return;
88-
}
89-
90-
void visitArchetypeType(ArchetypeType *archetype) {
91-
llvm_unreachable("Should not see archetypes in interface types");
92-
}
93-
94-
void visitGenericTypeParamType(GenericTypeParamType *param) {
95-
// Appears in protocols and in generic ObjC classes.
96-
return;
97-
}
98-
99-
void visitDependentMemberType(DependentMemberType *member) {
100-
// Appears in protocols and in generic ObjC classes.
101-
return;
102-
}
103-
104-
void visitAnyFunctionType(AnyFunctionType *fnTy) {
105-
for (auto &param : fnTy->getParams())
106-
visit(param.getOldType());
107-
visit(fnTy->getResult());
108-
}
109-
110-
void visitSyntaxSugarType(SyntaxSugarType *sugar) {
111-
visit(sugar->getSinglyDesugaredType());
112-
}
113-
114-
void visitProtocolCompositionType(ProtocolCompositionType *composition) {
115-
auto layout = composition->getExistentialLayout();
116-
if (auto superclass = layout.explicitSuperclass)
117-
visit(superclass);
118-
for (auto proto : layout.getProtocols())
119-
visit(proto);
120-
}
121-
122-
void visitLValueType(LValueType *lvalue) {
123-
llvm_unreachable("LValue types should not appear in interface types");
124-
}
125-
126-
void visitInOutType(InOutType *inout) {
127-
visit(inout->getObjectType());
64+
return Action::SkipChildren;
12865
}
12966

13067
/// Returns true if \p paramTy has any constraints other than being
@@ -138,7 +75,7 @@ class ReferencedTypeFinder : public TypeVisitor<ReferencedTypeFinder> {
13875
return !conformsTo.empty();
13976
}
14077

141-
void visitBoundGenericType(BoundGenericType *boundGeneric) {
78+
Action visitBoundGenericType(BoundGenericType *boundGeneric) override {
14279
auto *decl = boundGeneric->getDecl();
14380

14481
NeedsDefinition = true;
@@ -151,22 +88,22 @@ class ReferencedTypeFinder : public TypeVisitor<ReferencedTypeFinder> {
15188
for_each(boundGeneric->getGenericArgs(),
15289
sig->getInnermostGenericParams(),
15390
[&](Type argTy, GenericTypeParamType *paramTy) {
91+
// FIXME: I think there's a bug here with recursive generic types.
15492
if (isObjCGeneric && isConstrained(sig, paramTy))
15593
NeedsDefinition = true;
156-
visit(argTy);
94+
argTy.walk(*this);
15795
NeedsDefinition = false;
15896
});
97+
return Action::SkipChildren;
15998
}
16099

161100
public:
162-
using TypeVisitor::visit;
163-
164101
bool needsDefinition() const {
165102
return NeedsDefinition;
166103
}
167104

168-
static void walk(ModuleDecl &mod, Type ty, decltype(Callback) callback) {
169-
ReferencedTypeFinder(mod, callback).visit(ty);
105+
static void walk(Type ty, decltype(Callback) callback) {
106+
ty.walk(ReferencedTypeFinder(callback));
170107
}
171108
};
172109

@@ -330,7 +267,7 @@ class ModuleWriter {
330267
}
331268

332269
bool needsToBeIndividuallyDelayed = false;
333-
ReferencedTypeFinder::walk(M, VD->getInterfaceType(),
270+
ReferencedTypeFinder::walk(VD->getInterfaceType(),
334271
[&](ReferencedTypeFinder &finder,
335272
const TypeDecl *TD) {
336273
if (TD == container)

0 commit comments

Comments
 (0)