Skip to content

Commit 7beceb0

Browse files
committed
[AST] Generalize getInnermostClosureForSelfCapture
Really this applies to any capture, not just `self`. Also refactor to make it clear that parent closures and functions are really the only cases that matter here.
1 parent eef4716 commit 7beceb0

File tree

4 files changed

+21
-21
lines changed

4 files changed

+21
-21
lines changed

include/swift/AST/DeclContext.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -515,12 +515,12 @@ class alignas(1 << DeclContextAlignInBits) DeclContext
515515
const_cast<DeclContext *>(this)->getInnermostSkippedFunctionContext();
516516
}
517517

518-
/// Returns the innermost context that is a ClosureExpr, which defines how
519-
/// self behaves, unless within a type context that redefines self.
518+
/// Returns the innermost ClosureExpr context that can propagate its captures
519+
/// to this DeclContext.
520520
LLVM_READONLY
521-
ClosureExpr *getInnermostClosureForSelfCapture();
522-
const ClosureExpr *getInnermostClosureForSelfCapture() const {
523-
return const_cast<DeclContext *>(this)->getInnermostClosureForSelfCapture();
521+
ClosureExpr *getInnermostClosureForCaptures();
522+
const ClosureExpr *getInnermostClosureForCaptures() const {
523+
return const_cast<DeclContext *>(this)->getInnermostClosureForCaptures();
524524
}
525525

526526
/// Returns the semantic parent of this context. A context has a

lib/AST/DeclContext.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -280,21 +280,21 @@ DeclContext *DeclContext::getInnermostSkippedFunctionContext() {
280280
return nullptr;
281281
}
282282

283-
ClosureExpr *DeclContext::getInnermostClosureForSelfCapture() {
284-
auto dc = this;
285-
if (auto closure = dyn_cast<ClosureExpr>(dc)) {
286-
return closure;
287-
}
288-
289-
// Stop searching if we find a type decl, since types always
290-
// redefine what 'self' means, even when nested inside a closure.
291-
if (dc->isTypeContext()) {
292-
return nullptr;
293-
}
283+
ClosureExpr *DeclContext::getInnermostClosureForCaptures() {
284+
auto *DC = this;
285+
do {
286+
if (auto *CE = dyn_cast<ClosureExpr>(DC))
287+
return CE;
294288

295-
if (auto parent = dc->getParent()) {
296-
return parent->getInnermostClosureForSelfCapture();
297-
}
289+
// Autoclosures and AbstractFunctionDecls can propagate captures.
290+
switch (DC->getContextKind()) {
291+
case DeclContextKind::AbstractClosureExpr:
292+
case DeclContextKind::AbstractFunctionDecl:
293+
continue;
294+
default:
295+
return nullptr;
296+
}
297+
} while ((DC = DC->getParent()));
298298

299299
return nullptr;
300300
}

lib/AST/UnqualifiedLookup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ ValueDecl *UnqualifiedLookupFactory::lookupBaseDecl(const DeclContext *baseDC) c
362362
// Perform an unqualified lookup for the base decl of this result. This
363363
// handles cases where self was rebound (e.g. `guard let self = self`)
364364
// earlier in this closure or some outer closure.
365-
auto closureExpr = DC->getInnermostClosureForSelfCapture();
365+
auto closureExpr = DC->getInnermostClosureForCaptures();
366366
if (!closureExpr) {
367367
return nullptr;
368368
}

lib/Sema/MiscDiagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2221,7 +2221,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
22212221
return nullptr;
22222222
}
22232223

2224-
return parentContext->getInnermostClosureForSelfCapture();
2224+
return parentContext->getInnermostClosureForCaptures();
22252225
}
22262226

22272227
bool shouldRecordClosure(const AbstractClosureExpr *E) {

0 commit comments

Comments
 (0)