@@ -1784,15 +1784,34 @@ class ImplicitSelfUsageChecker : public BaseDiagnosticWalker {
17841784 return false ;
17851785 }
17861786
1787- // Require `LoadExpr`s when validating the self binding.
1788- // This lets us reject invalid examples like:
1789- //
1790- // let `self` = self ?? .somethingElse
1791- // guard let self = self else { return }
1792- // method() // <- implicit self is not allowed
1793- //
1794- return conditionalStmt->rebindsSelf (Ctx, /* requiresCaptureListRef*/ false ,
1795- /* requireLoadExpr*/ true );
1787+ if (Ctx.LangOpts .hasFeature (Feature::ImmutableWeakCaptures)) {
1788+ // Require that the RHS of the `let self = self` condition
1789+ // refers to a variable defined in a capture list.
1790+ // This lets us reject invalid examples like:
1791+ //
1792+ // var `self` = self ?? .somethingElse
1793+ // guard let self = self else { return }
1794+ // method() // <- implicit self is not allowed
1795+ //
1796+ // In 5.10, instead of this check, compiler was checking that RHS of the
1797+ // self binding is loaded from a mutable variable. This is incorrect, but
1798+ // before immutable weak captures compiler was trying to maintain this
1799+ // behavior in Swift 5 mode for source compatibility. With immutable weak
1800+ // captures this does not work anymore, because even in Swift 5 mode there
1801+ // is no `LoadExpr` to use.
1802+ //
1803+ return conditionalStmt->rebindsSelf (Ctx, /* requiresCaptureListRef*/ true );
1804+ } else {
1805+ // Require `LoadExpr`s when validating the self binding.
1806+ // This lets us reject invalid examples like:
1807+ //
1808+ // let `self` = self ?? .somethingElse
1809+ // guard let self = self else { return }
1810+ // method() // <- implicit self is not allowed
1811+ //
1812+ return conditionalStmt->rebindsSelf (Ctx, /* requiresCaptureListRef*/ false ,
1813+ /* requireLoadExpr*/ true );
1814+ }
17961815 }
17971816
17981817 static bool
@@ -4043,9 +4062,12 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
40434062
40444063 // If this variable has WeakStorageType, then it can be mutated in ways we
40454064 // don't know.
4046- if (var->getInterfaceType ()->is <WeakStorageType>())
4065+ if (var->getInterfaceType ()->is <WeakStorageType>() &&
4066+ (access & RK_CaptureList) &&
4067+ !DC->getASTContext ().LangOpts .hasFeature (
4068+ Feature::ImmutableWeakCaptures))
40474069 access |= RK_Written;
4048-
4070+
40494071 // Diagnose variables that were never used (other than their
40504072 // initialization).
40514073 //
@@ -4216,6 +4238,8 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
42164238 if (isUsedInInactive (var))
42174239 continue ;
42184240
4241+ bool isWeak = var->getInterfaceType ()->is <WeakStorageType>();
4242+
42194243 // If this is a parameter explicitly marked 'var', remove it.
42204244 if (FixItLoc.isInvalid ()) {
42214245 bool suggestCaseLet = false ;
@@ -4226,10 +4250,14 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
42264250 suggestCaseLet = isa<ForEachStmt>(stmt);
42274251 }
42284252 if (suggestCaseLet)
4229- Diags.diagnose (var->getLoc (), diag::variable_tuple_elt_never_mutated,
4253+ Diags.diagnose (var->getLoc (),
4254+ isWeak ? diag::weak_variable_tuple_elt_never_mutated
4255+ : diag::variable_tuple_elt_never_mutated,
42304256 var->getName (), var->getNameStr ());
42314257 else
4232- Diags.diagnose (var->getLoc (), diag::variable_never_mutated,
4258+ Diags.diagnose (var->getLoc (),
4259+ isWeak ? diag::weak_variable_never_mutated
4260+ : diag::variable_never_mutated,
42334261 var->getName (), true );
42344262
42354263 }
@@ -4242,7 +4270,9 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
42424270 suggestLet = !isa<ForEachStmt>(stmt);
42434271 }
42444272
4245- auto diag = Diags.diagnose (var->getLoc (), diag::variable_never_mutated,
4273+ auto diag = Diags.diagnose (var->getLoc (),
4274+ isWeak ? diag::weak_variable_never_mutated
4275+ : diag::variable_never_mutated,
42464276 var->getName (), suggestLet);
42474277
42484278 if (suggestLet)
0 commit comments