Skip to content

Commit fe272e6

Browse files
committed
[Sema] Restore 5.10 implicit self behavior prior to Swift 6 mode
Unfortunately we've encountered another source breaking case here: ``` class C { func method() {} func foo() { Task { [weak self] in Task { method() } } } } ``` In 5.10 we'd only do the unqualified lookup for `self` when directly in a `weak self` closure, but with the implicit self rework, we'd start using the `weak self` here, leading to a type-checker error. At this point, adding more edge cases to the existing logic is going to make things much more complicated. Instead, reinstate the 5.10 implicit self lookup behavior and diagnostic logic, switching over to the new logic only under Swift 6 mode. rdar://129475277
1 parent 4a49e65 commit fe272e6

File tree

6 files changed

+343
-260
lines changed

6 files changed

+343
-260
lines changed

lib/AST/UnqualifiedLookup.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -369,20 +369,24 @@ ValueDecl *UnqualifiedLookupFactory::lookupBaseDecl(const DeclContext *baseDC) c
369369
return nullptr;
370370
}
371371

372-
auto selfDecl = ASTScope::lookupSingleLocalDecl(
373-
DC->getParentSourceFile(), DeclName(Ctx.Id_self), Loc);
374-
375-
if (!selfDecl) {
376-
return nullptr;
377-
}
378-
379372
bool capturesSelfWeakly = false;
380373
if (auto decl = closureExpr->getCapturedSelfDecl()) {
381374
if (auto a = decl->getAttrs().getAttribute<ReferenceOwnershipAttr>()) {
382375
capturesSelfWeakly = a->get() == ReferenceOwnership::Weak;
383376
}
384377
}
385378

379+
// Previously we didn't perform the lookup of 'self' for anything outside
380+
// of a '[weak self]' closure, maintain that behavior until Swift 6 mode.
381+
if (!Ctx.LangOpts.isSwiftVersionAtLeast(6) && !capturesSelfWeakly)
382+
return nullptr;
383+
384+
auto selfDecl = ASTScope::lookupSingleLocalDecl(DC->getParentSourceFile(),
385+
DeclName(Ctx.Id_self), Loc);
386+
if (!selfDecl) {
387+
return nullptr;
388+
}
389+
386390
// In Swift 5 mode, implicit self is allowed within non-escaping
387391
// `weak self` closures even before self is unwrapped.
388392
// For example, this is allowed:
@@ -407,7 +411,7 @@ ValueDecl *UnqualifiedLookupFactory::lookupBaseDecl(const DeclContext *baseDC) c
407411
// In these cases, using the Swift 6 lookup behavior doesn't affect
408412
// how the body is type-checked, so it can be used in Swift 5 mode
409413
// without breaking source compatibility for non-escaping closures.
410-
if (capturesSelfWeakly && !Ctx.LangOpts.isSwiftVersionAtLeast(6) &&
414+
if (!Ctx.LangOpts.isSwiftVersionAtLeast(6) &&
411415
!implicitSelfReferenceIsUnwrapped(selfDecl)) {
412416
return nullptr;
413417
}

lib/Sema/MiscDiagnostics.cpp

Lines changed: 131 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,91 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
17151715
Closures.push_back(ACE);
17161716
}
17171717

1718+
static bool
1719+
implicitWeakSelfReferenceIsValid510(const DeclRefExpr *DRE,
1720+
const AbstractClosureExpr *inClosure) {
1721+
ASTContext &Ctx = DRE->getDecl()->getASTContext();
1722+
1723+
// Check if the implicit self decl refers to a var in a conditional stmt
1724+
LabeledConditionalStmt *conditionalStmt = nullptr;
1725+
if (auto var = dyn_cast<VarDecl>(DRE->getDecl())) {
1726+
if (auto parentStmt = var->getParentPatternStmt()) {
1727+
conditionalStmt = dyn_cast<LabeledConditionalStmt>(parentStmt);
1728+
}
1729+
}
1730+
1731+
if (!conditionalStmt) {
1732+
return false;
1733+
}
1734+
1735+
// Require `LoadExpr`s when validating the self binding.
1736+
// This lets us reject invalid examples like:
1737+
//
1738+
// let `self` = self ?? .somethingElse
1739+
// guard let self = self else { return }
1740+
// method() // <- implicit self is not allowed
1741+
//
1742+
return conditionalStmt->rebindsSelf(Ctx, /*requiresCaptureListRef*/ false,
1743+
/*requireLoadExpr*/ true);
1744+
}
1745+
1746+
static bool
1747+
isEnclosingSelfReference510(VarDecl *var,
1748+
const AbstractClosureExpr *inClosure) {
1749+
if (var->isSelfParameter())
1750+
return true;
1751+
1752+
// Capture variables have a DC of the parent function.
1753+
if (inClosure && var->isSelfParamCapture() &&
1754+
var->getDeclContext() != inClosure->getParent())
1755+
return true;
1756+
1757+
return false;
1758+
}
1759+
1760+
static bool
1761+
selfDeclAllowsImplicitSelf510(DeclRefExpr *DRE, Type ty,
1762+
const AbstractClosureExpr *inClosure) {
1763+
// If this is an explicit `weak self` capture, then implicit self is
1764+
// allowed once the closure's self param is unwrapped. We need to validate
1765+
// that the unwrapped `self` decl specifically refers to an unwrapped copy
1766+
// of the closure's `self` param, and not something else like in `guard
1767+
// let self = .someOptionalVariable else { return }` or `let self =
1768+
// someUnrelatedVariable`. If self hasn't been unwrapped yet and is still
1769+
// an optional, we would have already hit an error elsewhere.
1770+
if (closureHasWeakSelfCapture(inClosure)) {
1771+
return implicitWeakSelfReferenceIsValid510(DRE, inClosure);
1772+
}
1773+
1774+
// Metatype self captures don't extend the lifetime of an object.
1775+
if (ty->is<MetatypeType>())
1776+
return true;
1777+
1778+
// If self does not have reference semantics, it is very unlikely that
1779+
// capturing it will create a reference cycle.
1780+
if (!ty->hasReferenceSemantics())
1781+
return true;
1782+
1783+
if (auto closureExpr = dyn_cast<ClosureExpr>(inClosure)) {
1784+
if (auto selfDecl = closureExpr->getCapturedSelfDecl()) {
1785+
// If this capture is using the name `self` actually referring
1786+
// to some other variable (e.g. with `[self = "hello"]`)
1787+
// then implicit self is not allowed.
1788+
if (!selfDecl->isSelfParamCapture()) {
1789+
return false;
1790+
}
1791+
}
1792+
}
1793+
1794+
if (auto var = dyn_cast<VarDecl>(DRE->getDecl())) {
1795+
if (!isEnclosingSelfReference510(var, inClosure)) {
1796+
return true;
1797+
}
1798+
}
1799+
1800+
return false;
1801+
}
1802+
17181803
/// Whether or not implicit self is allowed for self decl
17191804
static bool
17201805
selfDeclAllowsImplicitSelf(Expr *E, const AbstractClosureExpr *inClosure) {
@@ -1731,6 +1816,11 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
17311816
if (!ty)
17321817
return true;
17331818

1819+
// Prior to Swift 6, use the old validation logic.
1820+
auto &ctx = inClosure->getASTContext();
1821+
if (!ctx.isSwiftVersionAtLeast(6))
1822+
return selfDeclAllowsImplicitSelf510(DRE, ty, inClosure);
1823+
17341824
return selfDeclAllowsImplicitSelf(DRE->getDecl(), ty, inClosure,
17351825
/*validateParentClosures:*/ true,
17361826
/*validateSelfRebindings:*/ true);
@@ -2063,8 +2153,9 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
20632153
/// Return true if this is a closure expression that will require explicit
20642154
/// use or capture of "self." for qualification of member references.
20652155
static bool
2066-
isClosureRequiringSelfQualification(const AbstractClosureExpr *CE) {
2067-
if (closureHasWeakSelfCapture(CE)) {
2156+
isClosureRequiringSelfQualification(const AbstractClosureExpr *CE,
2157+
bool ignoreWeakSelf = false) {
2158+
if (!ignoreWeakSelf && closureHasWeakSelfCapture(CE)) {
20682159
return true;
20692160
}
20702161

@@ -2110,9 +2201,20 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
21102201

21112202
bool shouldWalkCaptureInitializerExpressions() override { return true; }
21122203

2204+
bool shouldRecordClosure(const AbstractClosureExpr *E) {
2205+
// Record all closures in Swift 6 mode.
2206+
if (Ctx.isSwiftVersionAtLeast(6))
2207+
return true;
2208+
2209+
// Only record closures requiring self qualification prior to Swift 6
2210+
// mode.
2211+
return isClosureRequiringSelfQualification(E);
2212+
}
2213+
21132214
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
21142215
if (auto *CE = dyn_cast<AbstractClosureExpr>(E)) {
2115-
Closures.push_back(CE);
2216+
if (shouldRecordClosure(CE))
2217+
Closures.push_back(CE);
21162218
}
21172219

21182220
// If we aren't in a closure, no diagnostics will be produced.
@@ -2144,7 +2246,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
21442246
diag::property_use_in_closure_without_explicit_self,
21452247
baseName.getIdentifier())
21462248
.warnUntilSwiftVersionIf(
2147-
invalidImplicitSelfShouldOnlyWarn(MRE->getBase(), ACE), 6);
2249+
invalidImplicitSelfShouldOnlyWarn510(MRE->getBase(), ACE), 6);
21482250
}
21492251

21502252
// Handle method calls with a specific diagnostic + fixit.
@@ -2159,12 +2261,13 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
21592261
diag::method_call_in_closure_without_explicit_self,
21602262
MethodExpr->getDecl()->getBaseIdentifier())
21612263
.warnUntilSwiftVersionIf(
2162-
invalidImplicitSelfShouldOnlyWarn(DSCE->getBase(), ACE), 6);
2264+
invalidImplicitSelfShouldOnlyWarn510(DSCE->getBase(), ACE),
2265+
6);
21632266
}
21642267

21652268
if (memberLoc.isValid()) {
21662269
const AbstractClosureExpr *parentDisallowingImplicitSelf = nullptr;
2167-
if (selfDRE && selfDRE->getDecl()) {
2270+
if (Ctx.isSwiftVersionAtLeast(6) && selfDRE && selfDRE->getDecl()) {
21682271
parentDisallowingImplicitSelf = parentClosureDisallowingImplicitSelf(
21692272
selfDRE->getDecl(), selfDRE->getType(), ACE);
21702273
}
@@ -2173,11 +2276,11 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
21732276
return Action::SkipNode(E);
21742277
}
21752278

2176-
if (!selfDeclAllowsImplicitSelf(E, ACE))
2279+
if (!selfDeclAllowsImplicitSelf(E, ACE)) {
21772280
Diags.diagnose(E->getLoc(), diag::implicit_use_of_self_in_closure)
2178-
.warnUntilSwiftVersionIf(invalidImplicitSelfShouldOnlyWarn(E, ACE),
2179-
6);
2180-
2281+
.warnUntilSwiftVersionIf(
2282+
invalidImplicitSelfShouldOnlyWarn510(E, ACE), 6);
2283+
}
21812284
return Action::Continue(E);
21822285
}
21832286

@@ -2187,9 +2290,10 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
21872290
return Action::Continue(E);
21882291
}
21892292

2190-
assert(Closures.size() > 0);
2191-
Closures.pop_back();
2192-
2293+
if (shouldRecordClosure(ACE)) {
2294+
assert(Closures.size() > 0);
2295+
Closures.pop_back();
2296+
}
21932297
return Action::Continue(E);
21942298
}
21952299

@@ -2367,132 +2471,28 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
23672471

23682472
/// Whether or not this invalid usage of implicit self should be a warning
23692473
/// in Swift 5 mode, to preserve source compatibility.
2370-
bool invalidImplicitSelfShouldOnlyWarn(Expr *selfRef,
2371-
AbstractClosureExpr *ACE) {
2474+
bool invalidImplicitSelfShouldOnlyWarn510(Expr *selfRef,
2475+
AbstractClosureExpr *ACE) {
23722476
auto DRE = dyn_cast_or_null<DeclRefExpr>(selfRef);
2373-
if (!DRE) {
2477+
if (!DRE)
23742478
return false;
2375-
}
23762479

23772480
auto selfDecl = dyn_cast_or_null<VarDecl>(DRE->getDecl());
2378-
auto ty = DRE->getType();
2379-
if (!selfDecl) {
2380-
return false;
2381-
}
2382-
2383-
if (isInTypePreviouslyLackingValidation(ty)) {
2384-
return true;
2385-
}
2386-
2387-
if (isPreviouslyPermittedWeakSelfUsage(ACE, selfDecl, ty)) {
2388-
return true;
2389-
}
2390-
2391-
if (isUsageAlwaysPreviouslyRejected(selfDecl)) {
2481+
if (!selfDecl)
23922482
return false;
2393-
}
2394-
2395-
if (isPreviouslyPermittedStrongSelfUsage(selfDecl, ACE)) {
2396-
return true;
2397-
}
2398-
2399-
return false;
2400-
}
24012483

2402-
bool isInTypePreviouslyLackingValidation(Type ty) {
2403-
// We previously didn't validate captures at all in structs or metadata
2404-
// types, so we must only warn in this case.
2405-
return !ty->hasReferenceSemantics() || ty->is<MetatypeType>();
2406-
}
2407-
2408-
/// Checks if this usage of implicit self in a weak self closure
2409-
/// was previously permitted in Swift 5.8.
2410-
bool isPreviouslyPermittedWeakSelfUsage(AbstractClosureExpr *ACE,
2411-
ValueDecl *selfDecl, Type ty) {
2412-
auto weakSelfDecl = weakSelfCapture(ACE);
2413-
if (!weakSelfDecl) {
2414-
return false;
2415-
}
2416-
2417-
// Implicit self was permitted for weak self captures in
2418-
// non-escaping closures in Swift 5.7, so we must only warn.
2419-
if (isNonEscaping(ACE)) {
2420-
return true;
2421-
}
2422-
2423-
// Implicit self was also permitted for weak self captures in closures
2424-
// passed to @_implicitSelfCapture parameters in Swift 5.7.
2425-
if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
2426-
if (CE->allowsImplicitSelfCapture())
2427-
return true;
2428-
}
2429-
2430-
// Invalid captures like `[weak self = somethingElse]`
2431-
// were permitted in Swift 5.8, so we must only warn.
2432-
if (!isSimpleSelfCapture(weakSelfDecl)) {
2433-
return true;
2434-
}
2435-
2436-
if (auto condStmt = parentConditionalStmt(selfDecl)) {
2437-
auto isValidSelfRebinding = hasValidSelfRebinding(condStmt, Ctx);
2438-
2439-
// Swfit 5.8 permitted implicit self without validating any
2440-
// parent closures. If implicit self is only disallowed due to
2441-
// an invalid parent, we must only warn.
2442-
if (isValidSelfRebinding &&
2443-
implicitSelfDisallowedDueToInvalidParent(selfDecl, ty, ACE)) {
2444-
return true;
2445-
}
2446-
2447-
// Swift 5.8 used `requiresLoadExpr` to validate self bindings.
2448-
// If the binding is valid when only checking for a load expr,
2449-
// then we must only warn.
2450-
auto usesLoadExpr =
2451-
condStmt->rebindsSelf(Ctx, /*requiresCaptureListRef*/ false,
2452-
/*requireLoadExpr*/ true);
2453-
2454-
if (!isValidSelfRebinding && usesLoadExpr) {
2455-
return true;
2456-
}
2457-
}
2458-
2459-
return false;
2460-
}
2461-
2462-
/// Checks if this implicit self usage was always previously rejected as
2463-
/// invalid, so can continue to be treated an error.
2464-
bool isUsageAlwaysPreviouslyRejected(ValueDecl *selfDecl) {
2465-
// If the self decl refers to a weak self unwrap condition
2466-
// in some parent closure, then there is no source-compatibility
2467-
// requirement to avoid an error.
2468-
return hasValidSelfRebinding(parentConditionalStmt(selfDecl), Ctx);
2469-
}
2470-
2471-
/// Checks if this is a usage of implicit self in a strong self closure
2472-
/// that was previously permitted in older versions like Swift 5.3.
2473-
bool isPreviouslyPermittedStrongSelfUsage(VarDecl *selfDecl,
2474-
AbstractClosureExpr *ACE) {
2475-
// Implicit self was accidentially allowed in examples like this
2476-
// in Swift 5.3-5.5, so check for this case and emit a warning
2477-
// instead of an error:
2478-
//
2479-
// withEscaping { [self] in
2480-
// withEscaping {
2481-
// x += 1
2482-
// }
2483-
// }
2484-
//
2485-
bool isEscapingClosureWithExplicitSelfCapture = false;
2486-
if (!isNonEscaping(ACE)) {
2487-
if (auto closureExpr = dyn_cast<ClosureExpr>(ACE)) {
2488-
if (closureExpr->getCapturedSelfDecl()) {
2489-
isEscapingClosureWithExplicitSelfCapture = true;
2490-
}
2491-
}
2484+
// If this implicit self decl is from a closure that captured self
2485+
// weakly, then we should always emit an error, since implicit self was
2486+
// only allowed starting in Swift 5.8 and later.
2487+
if (closureHasWeakSelfCapture(ACE)) {
2488+
// Implicit self was incorrectly permitted for weak self captures
2489+
// in non-escaping closures in Swift 5.7, so in that case we can
2490+
// only warn until Swift 6.
2491+
return !isClosureRequiringSelfQualification(ACE,
2492+
/*ignoreWeakSelf*/ true);
24922493
}
24932494

2494-
return !selfDecl->isSelfParameter() &&
2495-
!isEscapingClosureWithExplicitSelfCapture;
2495+
return !selfDecl->isSelfParameter();
24962496
}
24972497
};
24982498

0 commit comments

Comments
 (0)