@@ -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;
@@ -7300,7 +7302,7 @@ static StorageMutability storageIsMutable(bool isMutable) {
73007302// / is a let member in an initializer.
73017303StorageMutability
73027304VarDecl::mutability (const DeclContext *UseDC,
7303- const DeclRefExpr *base) const {
7305+ std::optional< const DeclRefExpr *> base) const {
73047306 // Parameters are settable or not depending on their ownership convention.
73057307 if (auto *PD = dyn_cast<ParamDecl>(this ))
73067308 return storageIsMutable (!PD->isImmutableInFunctionBody ());
@@ -7310,9 +7312,12 @@ VarDecl::mutability(const DeclContext *UseDC,
73107312 if (!isLet ()) {
73117313 if (hasInitAccessor ()) {
73127314 if (auto *ctor = dyn_cast_or_null<ConstructorDecl>(UseDC)) {
7313- if (base && ctor->getImplicitSelfDecl () != base->getDecl ())
7314- return storageIsMutable (supportsMutation ());
7315- return StorageMutability::Initializable;
7315+ // If we're referencing 'self.', it's initializable.
7316+ if (!base ||
7317+ (*base && ctor->getImplicitSelfDecl () == (*base)->getDecl ()))
7318+ return StorageMutability::Initializable;
7319+
7320+ return storageIsMutable (supportsMutation ());
73167321 }
73177322 }
73187323
@@ -7370,17 +7375,18 @@ VarDecl::mutability(const DeclContext *UseDC,
73707375 getDeclContext ()->getSelfNominalTypeDecl ())
73717376 return StorageMutability::Immutable;
73727377
7373- if (base && CD->getImplicitSelfDecl () != base->getDecl ())
7374- return StorageMutability::Immutable;
7375-
73767378 // If this is a convenience initializer (i.e. one that calls
73777379 // self.init), then let properties are never mutable in it. They are
73787380 // only mutable in designated initializers.
73797381 auto initKindAndExpr = CD->getDelegatingOrChainedInitKind ();
73807382 if (initKindAndExpr.initKind == BodyInitKind::Delegating)
73817383 return StorageMutability::Immutable;
73827384
7383- return StorageMutability::Initializable;
7385+ // If we were given a base and it is 'self', it's initializable.
7386+ if (!base || (*base && CD->getImplicitSelfDecl () == (*base)->getDecl ()))
7387+ return StorageMutability::Initializable;
7388+
7389+ return StorageMutability::Immutable;
73847390 }
73857391
73867392 // If the 'let' has a value bound to it but has no PBD, then it is
0 commit comments