@@ -2004,6 +2004,30 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
2004
2004
diag.fixItInsertAfter (closureExpr->getLoc (), " [self] in" + trailing);
2005
2005
}
2006
2006
};
2007
+
2008
+ // A walker that verifies whether or not `exprToMatch`
2009
+ // is a descendent of the AST node being walked
2010
+ class ExprIsDescendantWalker : public BaseDiagnosticWalker {
2011
+ Expr *exprToMatch;
2012
+ public:
2013
+ bool exprIsDescendant = false ;
2014
+
2015
+ explicit ExprIsDescendantWalker (Expr *exprToMatch)
2016
+ : exprToMatch(exprToMatch) { }
2017
+
2018
+ bool shouldWalkIntoSeparatelyCheckedClosure (ClosureExpr *expr) override {
2019
+ return true ;
2020
+ }
2021
+
2022
+ PreWalkResult<Expr *> walkToExprPre (Expr *E) override {
2023
+ if (E == exprToMatch) {
2024
+ exprIsDescendant = true ;
2025
+ return Action::Stop ();
2026
+ }
2027
+
2028
+ return Action::Continue (E);
2029
+ }
2030
+ };
2007
2031
2008
2032
auto &ctx = DC->getASTContext ();
2009
2033
AbstractClosureExpr *ACE = nullptr ;
@@ -2015,6 +2039,18 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
2015
2039
DC = DC->getParent ();
2016
2040
}
2017
2041
}
2042
+
2043
+ // Verify E is actually a descendant of ACE before we use it.
2044
+ // Otherwise we'd be diagnosing E within the context of a closure
2045
+ // that it isn't actually a part of.
2046
+ if (ACE) {
2047
+ auto isDescendantWalker = ExprIsDescendantWalker (const_cast <Expr *>(E));
2048
+ ACE->walk (isDescendantWalker);
2049
+ if (!isDescendantWalker.exprIsDescendant ) {
2050
+ ACE = nullptr ;
2051
+ }
2052
+ }
2053
+
2018
2054
const_cast <Expr *>(E)->walk (DiagnoseWalker (ctx, ACE));
2019
2055
}
2020
2056
0 commit comments