Skip to content

Commit 4cd404d

Browse files
committed
[MiscDiagnostics] Introduce a base class for diagnostic walkers
Put some common logic related to local declaration to the base class and refactor other walkers to use it instead of `ASTWalker`.
1 parent f258a77 commit 4cd404d

File tree

3 files changed

+49
-26
lines changed

3 files changed

+49
-26
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/NameLookupRequests.h"
2525
#include "swift/AST/Pattern.h"
2626
#include "swift/AST/SourceFile.h"
27+
#include "swift/AST/Stmt.h"
2728
#include "swift/AST/TypeCheckRequests.h"
2829
#include "swift/Basic/Defer.h"
2930
#include "swift/Basic/SourceManager.h"
@@ -50,6 +51,37 @@ static Expr *isImplicitPromotionToOptional(Expr *E) {
5051
return nullptr;
5152
}
5253

54+
bool BaseDiagnosticWalker::walkToDeclPre(Decl *D) {
55+
return isa<ClosureExpr>(D->getDeclContext())
56+
? shouldWalkIntoDeclInClosureContext(D)
57+
: false;
58+
}
59+
60+
bool BaseDiagnosticWalker::shouldWalkIntoDeclInClosureContext(Decl *D) {
61+
auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext());
62+
assert(closure);
63+
64+
if (closure->isSeparatelyTypeChecked())
65+
return false;
66+
67+
auto &opts = D->getASTContext().TypeCheckerOpts;
68+
69+
// If multi-statement inference is enabled, let's not walk
70+
// into declarations contained in a multi-statement closure
71+
// because they'd be handled via `typeCheckDecl` that runs
72+
// syntactic diagnostics.
73+
if (opts.EnableMultiStatementClosureInference &&
74+
!closure->hasSingleExpressionBody()) {
75+
// Since pattern bindings get their types through solution application,
76+
// `typeCheckDecl` doesn't touch initializers (because they are already
77+
// fully type-checked), so pattern bindings have to be allowed to be
78+
// walked to diagnose syntactic issues.
79+
return isa<PatternBindingDecl>(D);
80+
}
81+
82+
return true;
83+
}
84+
5385
/// Diagnose syntactic restrictions of expressions.
5486
///
5587
/// - Module values may only occur as part of qualification.
@@ -72,7 +104,7 @@ static Expr *isImplicitPromotionToOptional(Expr *E) {
72104
///
73105
static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
74106
bool isExprStmt) {
75-
class DiagnoseWalker : public ASTWalker {
107+
class DiagnoseWalker : public BaseDiagnosticWalker {
76108
SmallPtrSet<Expr*, 4> AlreadyDiagnosedMetatypes;
77109
SmallPtrSet<DeclRefExpr*, 4> AlreadyDiagnosedBitCasts;
78110

@@ -89,18 +121,8 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
89121
return { false, P };
90122
}
91123

92-
bool walkToDeclPre(Decl *D) override {
93-
if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
94-
return !closure->isSeparatelyTypeChecked();
95-
return false;
96-
}
97-
98124
bool walkToTypeReprPre(TypeRepr *T) override { return true; }
99125

100-
bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
101-
return false;
102-
}
103-
104126
bool shouldWalkCaptureInitializerExpressions() override { return true; }
105127

106128
bool shouldWalkIntoTapExpression() override { return false; }
@@ -1449,7 +1471,7 @@ static void diagRecursivePropertyAccess(const Expr *E, const DeclContext *DC) {
14491471
/// confusion, so we force an explicit self.
14501472
static void diagnoseImplicitSelfUseInClosure(const Expr *E,
14511473
const DeclContext *DC) {
1452-
class DiagnoseWalker : public ASTWalker {
1474+
class DiagnoseWalker : public BaseDiagnosticWalker {
14531475
ASTContext &Ctx;
14541476
SmallVector<AbstractClosureExpr *, 4> Closures;
14551477
public:
@@ -1530,18 +1552,6 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
15301552
return true;
15311553
}
15321554

1533-
1534-
// Don't walk into nested decls.
1535-
bool walkToDeclPre(Decl *D) override {
1536-
if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
1537-
return !closure->isSeparatelyTypeChecked();
1538-
return false;
1539-
}
1540-
1541-
bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
1542-
return false;
1543-
}
1544-
15451555
bool shouldWalkCaptureInitializerExpressions() override { return true; }
15461556

15471557
bool shouldWalkIntoTapExpression() override { return false; }

lib/Sema/MiscDiagnostics.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef SWIFT_SEMA_MISC_DIAGNOSTICS_H
1414
#define SWIFT_SEMA_MISC_DIAGNOSTICS_H
1515

16+
#include "swift/AST/ASTWalker.h"
1617
#include "swift/AST/AttrKind.h"
1718
#include "swift/AST/Pattern.h"
1819
#include "swift/AST/Expr.h"
@@ -26,7 +27,9 @@ namespace swift {
2627
class AbstractFunctionDecl;
2728
class ApplyExpr;
2829
class CallExpr;
30+
class ClosureExpr;
2931
class DeclContext;
32+
class Decl;
3033
class Expr;
3134
class InFlightDiagnostic;
3235
class Stmt;
@@ -122,6 +125,17 @@ void checkPatternBindingDeclAsyncUsage(PatternBindingDecl *decl);
122125
bool diagnoseUnhandledThrowsInAsyncContext(DeclContext *dc,
123126
ForEachStmt *forEach);
124127

128+
class BaseDiagnosticWalker : public ASTWalker {
129+
bool walkToDeclPre(Decl *D) override;
130+
131+
bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
132+
return false;
133+
}
134+
135+
private:
136+
static bool shouldWalkIntoDeclInClosureContext(Decl *D);
137+
};
138+
125139
} // namespace swift
126140

127141
#endif // SWIFT_SEMA_MISC_DIAGNOSTICS_H

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3297,7 +3297,7 @@ void swift::diagnoseExprAvailability(const Expr *E, DeclContext *DC) {
32973297

32983298
namespace {
32993299

3300-
class StmtAvailabilityWalker : public ASTWalker {
3300+
class StmtAvailabilityWalker : public BaseDiagnosticWalker {
33013301
DeclContext *DC;
33023302
bool WalkRecursively;
33033303

@@ -3333,7 +3333,6 @@ class StmtAvailabilityWalker : public ASTWalker {
33333333
return std::make_pair(true, P);
33343334
}
33353335
};
3336-
33373336
}
33383337

33393338
void swift::diagnoseStmtAvailability(const Stmt *S, DeclContext *DC,

0 commit comments

Comments
 (0)