Skip to content

Commit 97178b2

Browse files
committed
Look up the outer self decl via the capture's parent initializer instead of ASTScope::lookupSingleLocalDecl
1 parent f21aee7 commit 97178b2

File tree

3 files changed

+45
-10
lines changed

3 files changed

+45
-10
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,11 +1836,6 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
18361836
static const AbstractClosureExpr *
18371837
parentClosureDisallowingImplicitSelf(const ValueDecl *selfDecl,
18381838
const AbstractClosureExpr *inClosure) {
1839-
ASTContext &ctx = inClosure->getASTContext();
1840-
if (!selfDecl) {
1841-
return nullptr;
1842-
}
1843-
18441839
// Find the outer decl that determines what self refers to in this
18451840
// closure.
18461841
// - If this is an escaping closure that captured self, then `selfDecl`
@@ -1851,12 +1846,15 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
18511846
const ValueDecl *outerSelfDecl = selfDecl;
18521847
if (auto closureExpr = dyn_cast<ClosureExpr>(inClosure)) {
18531848
if (auto capturedSelfDecl = closureExpr->getCapturedSelfDecl()) {
1854-
outerSelfDecl = ASTScope::lookupSingleLocalDecl(
1855-
inClosure->getParentSourceFile(), DeclName(ctx.Id_self),
1856-
capturedSelfDecl->getLoc());
1849+
// Retrieve the outer decl that the self capture refers to.
1850+
outerSelfDecl = getParentInitializerDecl(capturedSelfDecl);
18571851
}
18581852
}
18591853

1854+
if (!outerSelfDecl) {
1855+
return nullptr;
1856+
}
1857+
18601858
// Find the closest parent closure that contains the outer self decl,
18611859
// potentially also validating all intermediate closures.
18621860
auto outerClosure = inClosure;
@@ -2010,6 +2008,43 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
20102008
return false;
20112009
}
20122010

2011+
// Given a `self` decl that is a closure's `self` capture,
2012+
// retrieves and returns the decl that the capture refers to.
2013+
static ValueDecl *getParentInitializerDecl(const VarDecl *selfDecl) {
2014+
if (!selfDecl) {
2015+
return nullptr;
2016+
}
2017+
2018+
auto captureList = selfDecl->getParentCaptureList();
2019+
if (!captureList) {
2020+
return nullptr;
2021+
}
2022+
2023+
for (auto capture : captureList->getCaptureList()) {
2024+
if (capture.getVar() == selfDecl && capture.PBD) {
2025+
// We've found the `CaptureListEntry` that contains the `self`
2026+
// capture, now we can retrieve and inspect its parent initializer.
2027+
auto index = capture.PBD->getPatternEntryIndexForVarDecl(selfDecl);
2028+
auto parentInitializer = capture.PBD->getInit(index);
2029+
2030+
// Look through implicit conversions like `InjectIntoOptionalExpr`
2031+
if (auto implicitConversion =
2032+
dyn_cast_or_null<ImplicitConversionExpr>(parentInitializer)) {
2033+
parentInitializer = implicitConversion->getSubExpr();
2034+
}
2035+
2036+
auto DRE = dyn_cast_or_null<DeclRefExpr>(parentInitializer);
2037+
if (!DRE) {
2038+
return nullptr;
2039+
}
2040+
2041+
return DRE->getDecl();
2042+
}
2043+
}
2044+
2045+
return nullptr;
2046+
}
2047+
20132048
/// Return true if this is a closure expression that will require explicit
20142049
/// use or capture of "self." for qualification of member references.
20152050
static bool

test/expr/closure/closures.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1368,7 +1368,7 @@ class TestGithubIssue69911 {
13681368
}
13691369
}
13701370

1371-
doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in
1371+
doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}}
13721372
x += 1 // expected-error{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}}
13731373
self.x += 1
13741374
}

test/expr/closure/closures_swift6.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ class TestGithubIssue69911 {
504504
}
505505
}
506506

507-
doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in
507+
doVoidStuffNonEscaping { [self = TestGithubIssue69911()] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}}
508508
x += 1 // expected-error{{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}}
509509
self.x += 1
510510
}

0 commit comments

Comments
 (0)