@@ -1715,6 +1715,91 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
1715
1715
Closures.push_back (ACE);
1716
1716
}
1717
1717
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
+
1718
1803
// / Whether or not implicit self is allowed for self decl
1719
1804
static bool
1720
1805
selfDeclAllowsImplicitSelf (Expr *E, const AbstractClosureExpr *inClosure) {
@@ -1731,6 +1816,11 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
1731
1816
if (!ty)
1732
1817
return true ;
1733
1818
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
+
1734
1824
return selfDeclAllowsImplicitSelf (DRE->getDecl (), ty, inClosure,
1735
1825
/* validateParentClosures:*/ true ,
1736
1826
/* validateSelfRebindings:*/ true );
@@ -2063,8 +2153,9 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
2063
2153
// / Return true if this is a closure expression that will require explicit
2064
2154
// / use or capture of "self." for qualification of member references.
2065
2155
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)) {
2068
2159
return true ;
2069
2160
}
2070
2161
@@ -2102,9 +2193,20 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
2102
2193
2103
2194
bool shouldWalkCaptureInitializerExpressions () override { return true ; }
2104
2195
2196
+ bool shouldRecordClosure (const AbstractClosureExpr *E) {
2197
+ // Record all closures in Swift 6 mode.
2198
+ if (Ctx.isSwiftVersionAtLeast (6 ))
2199
+ return true ;
2200
+
2201
+ // Only record closures requiring self qualification prior to Swift 6
2202
+ // mode.
2203
+ return isClosureRequiringSelfQualification (E);
2204
+ }
2205
+
2105
2206
PreWalkResult<Expr *> walkToExprPre (Expr *E) override {
2106
2207
if (auto *CE = dyn_cast<AbstractClosureExpr>(E)) {
2107
- Closures.push_back (CE);
2208
+ if (shouldRecordClosure (CE))
2209
+ Closures.push_back (CE);
2108
2210
}
2109
2211
2110
2212
// If we aren't in a closure, no diagnostics will be produced.
@@ -2136,7 +2238,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
2136
2238
diag::property_use_in_closure_without_explicit_self,
2137
2239
baseName.getIdentifier ())
2138
2240
.warnUntilSwiftVersionIf (
2139
- invalidImplicitSelfShouldOnlyWarn (MRE->getBase (), ACE), 6 );
2241
+ invalidImplicitSelfShouldOnlyWarn510 (MRE->getBase (), ACE), 6 );
2140
2242
}
2141
2243
2142
2244
// Handle method calls with a specific diagnostic + fixit.
@@ -2151,12 +2253,13 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
2151
2253
diag::method_call_in_closure_without_explicit_self,
2152
2254
MethodExpr->getDecl ()->getBaseIdentifier ())
2153
2255
.warnUntilSwiftVersionIf (
2154
- invalidImplicitSelfShouldOnlyWarn (DSCE->getBase (), ACE), 6 );
2256
+ invalidImplicitSelfShouldOnlyWarn510 (DSCE->getBase (), ACE),
2257
+ 6 );
2155
2258
}
2156
2259
2157
2260
if (memberLoc.isValid ()) {
2158
2261
const AbstractClosureExpr *parentDisallowingImplicitSelf = nullptr ;
2159
- if (selfDRE && selfDRE->getDecl ()) {
2262
+ if (Ctx. isSwiftVersionAtLeast ( 6 ) && selfDRE && selfDRE->getDecl ()) {
2160
2263
parentDisallowingImplicitSelf = parentClosureDisallowingImplicitSelf (
2161
2264
selfDRE->getDecl (), selfDRE->getType (), ACE);
2162
2265
}
@@ -2165,11 +2268,11 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
2165
2268
return Action::SkipNode (E);
2166
2269
}
2167
2270
2168
- if (!selfDeclAllowsImplicitSelf (E, ACE))
2271
+ if (!selfDeclAllowsImplicitSelf (E, ACE)) {
2169
2272
Diags.diagnose (E->getLoc (), diag::implicit_use_of_self_in_closure)
2170
- .warnUntilSwiftVersionIf (invalidImplicitSelfShouldOnlyWarn (E, ACE),
2171
- 6 );
2172
-
2273
+ .warnUntilSwiftVersionIf (
2274
+ invalidImplicitSelfShouldOnlyWarn510 (E, ACE), 6 );
2275
+ }
2173
2276
return Action::Continue (E);
2174
2277
}
2175
2278
@@ -2179,9 +2282,10 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
2179
2282
return Action::Continue (E);
2180
2283
}
2181
2284
2182
- assert (Closures.size () > 0 );
2183
- Closures.pop_back ();
2184
-
2285
+ if (shouldRecordClosure (ACE)) {
2286
+ assert (Closures.size () > 0 );
2287
+ Closures.pop_back ();
2288
+ }
2185
2289
return Action::Continue (E);
2186
2290
}
2187
2291
@@ -2359,134 +2463,28 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
2359
2463
2360
2464
// / Whether or not this invalid usage of implicit self should be a warning
2361
2465
// / in Swift 5 mode, to preserve source compatibility.
2362
- bool invalidImplicitSelfShouldOnlyWarn (Expr *selfRef,
2363
- AbstractClosureExpr *ACE) {
2466
+ bool invalidImplicitSelfShouldOnlyWarn510 (Expr *selfRef,
2467
+ AbstractClosureExpr *ACE) {
2364
2468
auto DRE = dyn_cast_or_null<DeclRefExpr>(selfRef);
2365
- if (!DRE) {
2469
+ if (!DRE)
2366
2470
return false ;
2367
- }
2368
2471
2369
2472
auto selfDecl = dyn_cast_or_null<VarDecl>(DRE->getDecl ());
2370
- auto ty = DRE->getType ();
2371
- if (!selfDecl) {
2372
- return false ;
2373
- }
2374
-
2375
- if (isInTypePreviouslyLackingValidation (ty)) {
2376
- return true ;
2377
- }
2378
-
2379
- if (isPreviouslyPermittedWeakSelfUsage (ACE, selfDecl, ty)) {
2380
- return true ;
2381
- }
2382
-
2383
- if (isUsageAlwaysPreviouslyRejected (selfDecl)) {
2473
+ if (!selfDecl)
2384
2474
return false ;
2385
- }
2386
-
2387
- if (isPreviouslyPermittedStrongSelfUsage (selfDecl, ACE)) {
2388
- return true ;
2389
- }
2390
-
2391
- return false ;
2392
- }
2393
2475
2394
- bool isInTypePreviouslyLackingValidation (Type ty) {
2395
- // We previously didn't validate captures at all in structs or metadata
2396
- // types, so we must only warn in this case.
2397
- return !ty->hasReferenceSemantics () || ty->is <MetatypeType>();
2398
- }
2399
-
2400
- // / Checks if this usage of implicit self in a weak self closure
2401
- // / was previously permitted in Swift 5.8.
2402
- bool isPreviouslyPermittedWeakSelfUsage (AbstractClosureExpr *ACE,
2403
- ValueDecl *selfDecl, Type ty) {
2404
- auto weakSelfDecl = weakSelfCapture (ACE);
2405
- if (!weakSelfDecl) {
2406
- return false ;
2407
- }
2408
-
2409
- // Implicit self was permitted for weak self captures in
2410
- // non-escaping closures in Swift 5.7, so we must only warn.
2411
- if (AnyFunctionRef (const_cast <AbstractClosureExpr *>(ACE))
2412
- .isKnownNoEscape ()) {
2413
- return true ;
2414
- }
2415
-
2416
- // Implicit self was also permitted for weak self captures in closures
2417
- // passed to @_implicitSelfCapture parameters in Swift 5.7.
2418
- if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
2419
- if (CE->allowsImplicitSelfCapture ())
2420
- return true ;
2421
- }
2422
-
2423
- // Invalid captures like `[weak self = somethingElse]`
2424
- // were permitted in Swift 5.8, so we must only warn.
2425
- if (!isSimpleSelfCapture (weakSelfDecl)) {
2426
- return true ;
2427
- }
2428
-
2429
- if (auto condStmt = parentConditionalStmt (selfDecl)) {
2430
- auto isValidSelfRebinding = hasValidSelfRebinding (condStmt, Ctx);
2431
-
2432
- // Swfit 5.8 permitted implicit self without validating any
2433
- // parent closures. If implicit self is only disallowed due to
2434
- // an invalid parent, we must only warn.
2435
- if (isValidSelfRebinding &&
2436
- implicitSelfDisallowedDueToInvalidParent (selfDecl, ty, ACE)) {
2437
- return true ;
2438
- }
2439
-
2440
- // Swift 5.8 used `requiresLoadExpr` to validate self bindings.
2441
- // If the binding is valid when only checking for a load expr,
2442
- // then we must only warn.
2443
- auto usesLoadExpr =
2444
- condStmt->rebindsSelf (Ctx, /* requiresCaptureListRef*/ false ,
2445
- /* requireLoadExpr*/ true );
2446
-
2447
- if (!isValidSelfRebinding && usesLoadExpr) {
2448
- return true ;
2449
- }
2450
- }
2451
-
2452
- return false ;
2453
- }
2454
-
2455
- // / Checks if this implicit self usage was always previously rejected as
2456
- // / invalid, so can continue to be treated an error.
2457
- bool isUsageAlwaysPreviouslyRejected (ValueDecl *selfDecl) {
2458
- // If the self decl refers to a weak self unwrap condition
2459
- // in some parent closure, then there is no source-compatibility
2460
- // requirement to avoid an error.
2461
- return hasValidSelfRebinding (parentConditionalStmt (selfDecl), Ctx);
2462
- }
2463
-
2464
- // / Checks if this is a usage of implicit self in a strong self closure
2465
- // / that was previously permitted in older versions like Swift 5.3.
2466
- bool isPreviouslyPermittedStrongSelfUsage (VarDecl *selfDecl,
2467
- AbstractClosureExpr *ACE) {
2468
- // Implicit self was accidentially allowed in examples like this
2469
- // in Swift 5.3-5.5, so check for this case and emit a warning
2470
- // instead of an error:
2471
- //
2472
- // withEscaping { [self] in
2473
- // withEscaping {
2474
- // x += 1
2475
- // }
2476
- // }
2477
- //
2478
- bool isEscapingClosureWithExplicitSelfCapture = false ;
2479
- if (!AnyFunctionRef (const_cast <AbstractClosureExpr *>(ACE))
2480
- .isKnownNoEscape ()) {
2481
- if (auto closureExpr = dyn_cast<ClosureExpr>(ACE)) {
2482
- if (closureExpr->getCapturedSelfDecl ()) {
2483
- isEscapingClosureWithExplicitSelfCapture = true ;
2484
- }
2485
- }
2476
+ // If this implicit self decl is from a closure that captured self
2477
+ // weakly, then we should always emit an error, since implicit self was
2478
+ // only allowed starting in Swift 5.8 and later.
2479
+ if (closureHasWeakSelfCapture (ACE)) {
2480
+ // Implicit self was incorrectly permitted for weak self captures
2481
+ // in non-escaping closures in Swift 5.7, so in that case we can
2482
+ // only warn until Swift 6.
2483
+ return !isClosureRequiringSelfQualification (ACE,
2484
+ /* ignoreWeakSelf*/ true );
2486
2485
}
2487
2486
2488
- return !selfDecl->isSelfParameter () &&
2489
- !isEscapingClosureWithExplicitSelfCapture;
2487
+ return !selfDecl->isSelfParameter ();
2490
2488
}
2491
2489
};
2492
2490
0 commit comments