@@ -2004,6 +2004,30 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
20042004 diag.fixItInsertAfter (closureExpr->getLoc (), " [self] in" + trailing);
20052005 }
20062006 };
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+ };
20072031
20082032 auto &ctx = DC->getASTContext ();
20092033 AbstractClosureExpr *ACE = nullptr ;
@@ -2015,6 +2039,18 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
20152039 DC = DC->getParent ();
20162040 }
20172041 }
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+
20182054 const_cast <Expr *>(E)->walk (DiagnoseWalker (ctx, ACE));
20192055}
20202056
0 commit comments