Skip to content

Commit 8ab27fc

Browse files
committed
Use Type.findIf instead of TypeVisitor to avoid missing parent type
1 parent 13a5c2d commit 8ab27fc

File tree

1 file changed

+44
-75
lines changed

1 file changed

+44
-75
lines changed

lib/Sema/PerformanceHints.cpp

Lines changed: 44 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -67,87 +67,56 @@ void checkImplicitCopyReturnType(const ClosureExpr *Closure,
6767
}
6868
}
6969

70-
class CheckExistentialAny : public TypeVisitor<CheckExistentialAny, bool> {
71-
public:
72-
static bool inType(Type type) {
73-
return CheckExistentialAny().visit(type->getCanonicalType());
74-
}
75-
76-
static void inFunctionReturnType(FuncDecl *FD, DiagnosticEngine &Diags) {
77-
Type T = FD->getResultInterfaceType();
78-
79-
if (inType(T))
80-
Diags.diagnose(FD, diag::perf_hint_func_returns_existential_any, FD);
81-
}
82-
83-
static void inClosureReturnType(ClosureExpr *CE, DiagnosticEngine &Diags) {
84-
Type T = CE->getResultType();
85-
86-
if (inType(T))
87-
Diags.diagnose(CE->getLoc(),
88-
diag::perf_hint_closure_returns_existential_any);
89-
}
90-
91-
static void inVariableType(const VarDecl *VD, DiagnosticEngine &Diags) {
92-
Type T = VD->getInterfaceType();
70+
bool isExistentialType(Type T) {
71+
return dyn_cast<ExistentialType>(T) != nullptr;
72+
}
9373

94-
if (inType(T))
95-
Diags.diagnose(VD, diag::perf_hint_var_uses_existential_any, VD);
96-
}
74+
bool hasExistentialAnyInType(Type type) {
75+
return type->getCanonicalType().findIf(isExistentialType);
76+
}
9777

98-
static void inPatternType(const AnyPattern *AP, DiagnosticEngine &Diags) {
99-
Type T = AP->getType();
78+
void checkExistentialAnyInFunctionReturnType(FuncDecl *FD,
79+
DiagnosticEngine &Diags) {
80+
Type T = FD->getResultInterfaceType();
10081

101-
if (inType(T))
102-
Diags.diagnose(AP->getLoc(),
103-
diag::perf_hint_any_pattern_uses_existential_any);
104-
}
82+
if (hasExistentialAnyInType(T))
83+
Diags.diagnose(FD, diag::perf_hint_func_returns_existential_any, FD);
84+
}
10585

106-
static void inTypeAlias(const TypeAliasDecl *TAD, DiagnosticEngine &Diags) {
107-
Type T = TAD->getUnderlyingType();
86+
void checkExistentialAnyInClosureReturnType(ClosureExpr *CE,
87+
DiagnosticEngine &Diags) {
88+
Type T = CE->getResultType();
10889

109-
if (inType(T))
110-
Diags.diagnose(TAD->getLoc(),
111-
diag::perf_hint_typealias_uses_existential_any, TAD);
112-
}
90+
if (hasExistentialAnyInType(T))
91+
Diags.diagnose(CE->getLoc(),
92+
diag::perf_hint_closure_returns_existential_any);
93+
}
11394

114-
bool visitExistentialType(ExistentialType *ET) {
115-
return true;
116-
}
95+
void checkExistentialAnyInVariableType(const VarDecl *VD,
96+
DiagnosticEngine &Diags) {
97+
Type T = VD->getInterfaceType();
11798

118-
bool visitTupleType(TupleType *TT) {
119-
for (const auto &element : TT->getElements()) {
120-
if (visit(element.getType())) {
121-
return true;
122-
}
123-
}
124-
return false;
125-
}
99+
if (hasExistentialAnyInType(T))
100+
Diags.diagnose(VD, diag::perf_hint_var_uses_existential_any, VD);
101+
}
126102

127-
bool visitBoundGenericType(BoundGenericType *BGT) {
128-
// Check generic arguments (e.g., Array<any Protocol>)
129-
for (Type arg : BGT->getGenericArgs()) {
130-
if (visit(arg)) {
131-
return true;
132-
}
133-
}
134-
return false;
135-
}
103+
void checkExistentialAnyInPatternType(const AnyPattern *AP,
104+
DiagnosticEngine &Diags) {
105+
Type T = AP->getType();
136106

137-
bool visitFunctionType(FunctionType *FT) {
138-
for (const auto &param : FT->getParams()) {
139-
if (visit(param.getPlainType()->getCanonicalType())) {
140-
return true;
141-
}
142-
}
107+
if (hasExistentialAnyInType(T))
108+
Diags.diagnose(AP->getLoc(),
109+
diag::perf_hint_any_pattern_uses_existential_any);
110+
}
143111

144-
return visit(FT->getResult()->getCanonicalType());
145-
}
112+
void checkExistentialAnyInTypeAlias(const TypeAliasDecl *TAD,
113+
DiagnosticEngine &Diags) {
114+
Type T = TAD->getUnderlyingType();
146115

147-
bool visitType(TypeBase *T) {
148-
return false;
149-
}
150-
};
116+
if (hasExistentialAnyInType(T))
117+
Diags.diagnose(TAD->getLoc(),
118+
diag::perf_hint_typealias_uses_existential_any, TAD);
119+
}
151120

152121
/// Produce performance hint diagnostics for a SourceFile.
153122
class PerformanceHintDiagnosticWalker final : public ASTWalker {
@@ -166,7 +135,7 @@ class PerformanceHintDiagnosticWalker final : public ASTWalker {
166135
return Action::SkipNode(P);
167136

168137
if (const AnyPattern *AP = dyn_cast<AnyPattern>(P)) {
169-
CheckExistentialAny::inPatternType(AP, Ctx.Diags);
138+
checkExistentialAnyInPatternType(AP, Ctx.Diags);
170139
}
171140

172141
return Action::Continue(P);
@@ -189,7 +158,7 @@ class PerformanceHintDiagnosticWalker final : public ASTWalker {
189158
"Traversing implicit expressions is disabled in the pre-walk visitor");
190159

191160
if (auto Closure = dyn_cast<ClosureExpr>(E)) {
192-
CheckExistentialAny::inClosureReturnType(Closure, Ctx.Diags);
161+
checkExistentialAnyInClosureReturnType(Closure, Ctx.Diags);
193162
}
194163

195164
return Action::Continue(E);
@@ -202,9 +171,9 @@ class PerformanceHintDiagnosticWalker final : public ASTWalker {
202171
if (const FuncDecl *FD = dyn_cast<FuncDecl>(D)) {
203172
checkImplicitCopyReturnType(FD, Ctx.Diags);
204173
} else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
205-
CheckExistentialAny::inVariableType(VD, Ctx.Diags);
174+
checkExistentialAnyInVariableType(VD, Ctx.Diags);
206175
} else if (const TypeAliasDecl *TAD = dyn_cast<TypeAliasDecl>(D)) {
207-
CheckExistentialAny::inTypeAlias(TAD, Ctx.Diags);
176+
checkExistentialAnyInTypeAlias(TAD, Ctx.Diags);
208177
}
209178

210179
return Action::Continue();
@@ -216,7 +185,7 @@ class PerformanceHintDiagnosticWalker final : public ASTWalker {
216185
"Traversing implicit declarations is disabled in the pre-walk visitor");
217186

218187
if (auto *FD = dyn_cast<FuncDecl>(D)) {
219-
CheckExistentialAny::inFunctionReturnType(FD, Ctx.Diags);
188+
checkExistentialAnyInFunctionReturnType(FD, Ctx.Diags);
220189
}
221190

222191
return Action::Continue();

0 commit comments

Comments
 (0)