@@ -3093,7 +3093,7 @@ bool AbstractStorageDecl::isSetterMutating() const {
30933093
30943094StorageMutability
30953095AbstractStorageDecl::mutability (const DeclContext *useDC,
3096- const DeclRefExpr *base) const {
3096+ std::optional< const DeclRefExpr *> base ) const {
30973097 if (auto vd = dyn_cast<VarDecl>(this ))
30983098 return vd->mutability (useDC, base);
30993099
@@ -3109,8 +3109,10 @@ AbstractStorageDecl::mutability(const DeclContext *useDC,
31093109// / 'optional' storage requirements, which lack support for direct
31103110// / writes in Swift.
31113111StorageMutability
3112- AbstractStorageDecl::mutabilityInSwift (const DeclContext *useDC,
3113- const DeclRefExpr *base) const {
3112+ AbstractStorageDecl::mutabilityInSwift (
3113+ const DeclContext *useDC,
3114+ std::optional<const DeclRefExpr *> base
3115+ ) const {
31143116 // TODO: Writing to an optional storage requirement is not supported in Swift.
31153117 if (getAttrs ().hasAttribute <OptionalAttr>()) {
31163118 return StorageMutability::Immutable;
@@ -7312,7 +7314,7 @@ static StorageMutability storageIsMutable(bool isMutable) {
73127314// / is a let member in an initializer.
73137315StorageMutability
73147316VarDecl::mutability (const DeclContext *UseDC,
7315- const DeclRefExpr *base) const {
7317+ std::optional< const DeclRefExpr *> base) const {
73167318 // Parameters are settable or not depending on their ownership convention.
73177319 if (auto *PD = dyn_cast<ParamDecl>(this ))
73187320 return storageIsMutable (!PD->isImmutableInFunctionBody ());
@@ -7322,9 +7324,12 @@ VarDecl::mutability(const DeclContext *UseDC,
73227324 if (!isLet ()) {
73237325 if (hasInitAccessor ()) {
73247326 if (auto *ctor = dyn_cast_or_null<ConstructorDecl>(UseDC)) {
7325- if (base && ctor->getImplicitSelfDecl () != base->getDecl ())
7326- return storageIsMutable (supportsMutation ());
7327- return StorageMutability::Initializable;
7327+ // If we're referencing 'self.', it's initializable.
7328+ if (!base ||
7329+ (*base && ctor->getImplicitSelfDecl () == (*base)->getDecl ()))
7330+ return StorageMutability::Initializable;
7331+
7332+ return storageIsMutable (supportsMutation ());
73287333 }
73297334 }
73307335
@@ -7382,17 +7387,18 @@ VarDecl::mutability(const DeclContext *UseDC,
73827387 getDeclContext ()->getSelfNominalTypeDecl ())
73837388 return StorageMutability::Immutable;
73847389
7385- if (base && CD->getImplicitSelfDecl () != base->getDecl ())
7386- return StorageMutability::Immutable;
7387-
73887390 // If this is a convenience initializer (i.e. one that calls
73897391 // self.init), then let properties are never mutable in it. They are
73907392 // only mutable in designated initializers.
73917393 auto initKindAndExpr = CD->getDelegatingOrChainedInitKind ();
73927394 if (initKindAndExpr.initKind == BodyInitKind::Delegating)
73937395 return StorageMutability::Immutable;
73947396
7395- return StorageMutability::Initializable;
7397+ // If we were given a base and it is 'self', it's initializable.
7398+ if (!base || (*base && CD->getImplicitSelfDecl () == (*base)->getDecl ()))
7399+ return StorageMutability::Initializable;
7400+
7401+ return StorageMutability::Immutable;
73967402 }
73977403
73987404 // If the 'let' has a value bound to it but has no PBD, then it is
0 commit comments