@@ -1781,23 +1781,34 @@ class ImplicitSelfUsageChecker : public BaseDiagnosticWalker {
17811781 return false ;
17821782 }
17831783
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+ }
18011812 }
18021813
18031814 static bool
@@ -4087,6 +4098,14 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
40874098 access &= ~RK_Written;
40884099 }
40894100
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+
40904109 // Diagnose variables that were never used (other than their
40914110 // initialization).
40924111 //
@@ -4257,6 +4276,8 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
42574276 if (isUsedInInactive (var))
42584277 continue ;
42594278
4279+ bool isWeak = var->getInterfaceType ()->is <WeakStorageType>();
4280+
42604281 // If this is a parameter explicitly marked 'var', remove it.
42614282 if (FixItLoc.isInvalid ()) {
42624283 bool suggestCaseLet = false ;
@@ -4267,10 +4288,14 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
42674288 suggestCaseLet = isa<ForEachStmt>(stmt);
42684289 }
42694290 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,
42714294 var->getName (), var->getNameStr ());
42724295 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,
42744299 var->getName (), true );
42754300
42764301 }
@@ -4283,7 +4308,9 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
42834308 suggestLet = !isa<ForEachStmt>(stmt);
42844309 }
42854310
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,
42874314 var->getName (), suggestLet);
42884315
42894316 if (suggestLet)
0 commit comments