@@ -1781,23 +1781,34 @@ class ImplicitSelfUsageChecker : public BaseDiagnosticWalker {
1781
1781
return false ;
1782
1782
}
1783
1783
1784
- // Require that the RHS of the `let self = self` condition
1785
- // refers to a variable defined in a capture list.
1786
- // This lets us reject invalid examples like:
1787
- //
1788
- // var `self` = self ?? .somethingElse
1789
- // guard let self = self else { return }
1790
- // method() // <- implicit self is not allowed
1791
- //
1792
- // In 5.10, instead of this check, compiler was checking that RHS of the
1793
- // self binding is loaded from a mutable variable. This is incorrect, but
1794
- // before SE-0481 compiler was trying to maintain this behavior in Swift 5
1795
- // mode for source compatibility. After SE-0481 this does not work
1796
- // anymore, because even in Swift 5 mode `weak self` capture is not mutable.
1797
- // So we have to introduce a breaking change as part of the SE-0481, and use
1798
- // proper check for capture list even in Swift 5 mode.
1799
- //
1800
- return conditionalStmt->rebindsSelf (Ctx, /* requiresCaptureListRef*/ true );
1784
+ if (Ctx.LangOpts .hasFeature (Feature::ImmutableWeakCaptures)) {
1785
+ // Require that the RHS of the `let self = self` condition
1786
+ // refers to a variable defined in a capture list.
1787
+ // This lets us reject invalid examples like:
1788
+ //
1789
+ // var `self` = self ?? .somethingElse
1790
+ // guard let self = self else { return }
1791
+ // method() // <- implicit self is not allowed
1792
+ //
1793
+ // In 5.10, instead of this check, compiler was checking that RHS of the
1794
+ // self binding is loaded from a mutable variable. This is incorrect, but
1795
+ // before immutable weak captures compiler was trying to maintain this
1796
+ // behavior in Swift 5 mode for source compatibility. With immutable weak
1797
+ // captures this does not work anymore, because even in Swift 5 mode there
1798
+ // is no `LoadExpr` to use.
1799
+ //
1800
+ return conditionalStmt->rebindsSelf (Ctx, /* requiresCaptureListRef*/ true );
1801
+ } else {
1802
+ // Require `LoadExpr`s when validating the self binding.
1803
+ // This lets us reject invalid examples like:
1804
+ //
1805
+ // let `self` = self ?? .somethingElse
1806
+ // guard let self = self else { return }
1807
+ // method() // <- implicit self is not allowed
1808
+ //
1809
+ return conditionalStmt->rebindsSelf (Ctx, /* requiresCaptureListRef*/ false ,
1810
+ /* requireLoadExpr*/ true );
1811
+ }
1801
1812
}
1802
1813
1803
1814
static bool
@@ -4087,6 +4098,14 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
4087
4098
access &= ~RK_Written;
4088
4099
}
4089
4100
4101
+ // If this variable has WeakStorageType, then it can be mutated in ways we
4102
+ // don't know.
4103
+ if (var->getInterfaceType ()->is <WeakStorageType>() &&
4104
+ (access & RK_CaptureList) &&
4105
+ !DC->getASTContext ().LangOpts .hasFeature (
4106
+ Feature::ImmutableWeakCaptures))
4107
+ access |= RK_Written;
4108
+
4090
4109
// Diagnose variables that were never used (other than their
4091
4110
// initialization).
4092
4111
//
@@ -4257,6 +4276,8 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
4257
4276
if (isUsedInInactive (var))
4258
4277
continue ;
4259
4278
4279
+ bool isWeak = var->getInterfaceType ()->is <WeakStorageType>();
4280
+
4260
4281
// If this is a parameter explicitly marked 'var', remove it.
4261
4282
if (FixItLoc.isInvalid ()) {
4262
4283
bool suggestCaseLet = false ;
@@ -4267,10 +4288,14 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
4267
4288
suggestCaseLet = isa<ForEachStmt>(stmt);
4268
4289
}
4269
4290
if (suggestCaseLet)
4270
- Diags.diagnose (var->getLoc (), diag::variable_tuple_elt_never_mutated,
4291
+ Diags.diagnose (var->getLoc (),
4292
+ isWeak ? diag::weak_variable_tuple_elt_never_mutated
4293
+ : diag::variable_tuple_elt_never_mutated,
4271
4294
var->getName (), var->getNameStr ());
4272
4295
else
4273
- Diags.diagnose (var->getLoc (), diag::variable_never_mutated,
4296
+ Diags.diagnose (var->getLoc (),
4297
+ isWeak ? diag::weak_variable_never_mutated
4298
+ : diag::variable_never_mutated,
4274
4299
var->getName (), true );
4275
4300
4276
4301
}
@@ -4283,7 +4308,9 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
4283
4308
suggestLet = !isa<ForEachStmt>(stmt);
4284
4309
}
4285
4310
4286
- auto diag = Diags.diagnose (var->getLoc (), diag::variable_never_mutated,
4311
+ auto diag = Diags.diagnose (var->getLoc (),
4312
+ isWeak ? diag::weak_variable_never_mutated
4313
+ : diag::variable_never_mutated,
4287
4314
var->getName (), suggestLet);
4288
4315
4289
4316
if (suggestLet)
0 commit comments