@@ -3087,7 +3087,7 @@ bool AbstractStorageDecl::isSetterMutating() const {
30873087
30883088StorageMutability
30893089AbstractStorageDecl::mutability (const DeclContext *useDC,
3090- const DeclRefExpr *base) const {
3090+ std::optional< const DeclRefExpr *> base ) const {
30913091 if (auto vd = dyn_cast<VarDecl>(this ))
30923092 return vd->mutability (useDC, base);
30933093
@@ -3103,8 +3103,10 @@ AbstractStorageDecl::mutability(const DeclContext *useDC,
31033103// / 'optional' storage requirements, which lack support for direct
31043104// / writes in Swift.
31053105StorageMutability
3106- AbstractStorageDecl::mutabilityInSwift (const DeclContext *useDC,
3107- const DeclRefExpr *base) const {
3106+ AbstractStorageDecl::mutabilityInSwift (
3107+ const DeclContext *useDC,
3108+ std::optional<const DeclRefExpr *> base
3109+ ) const {
31083110 // TODO: Writing to an optional storage requirement is not supported in Swift.
31093111 if (getAttrs ().hasAttribute <OptionalAttr>()) {
31103112 return StorageMutability::Immutable;
@@ -7392,7 +7394,7 @@ static StorageMutability storageIsMutable(bool isMutable) {
73927394// / is a let member in an initializer.
73937395StorageMutability
73947396VarDecl::mutability (const DeclContext *UseDC,
7395- const DeclRefExpr *base) const {
7397+ std::optional< const DeclRefExpr *> base) const {
73967398 // Parameters are settable or not depending on their ownership convention.
73977399 if (auto *PD = dyn_cast<ParamDecl>(this ))
73987400 return storageIsMutable (!PD->isImmutableInFunctionBody ());
@@ -7402,9 +7404,12 @@ VarDecl::mutability(const DeclContext *UseDC,
74027404 if (!isLet ()) {
74037405 if (hasInitAccessor ()) {
74047406 if (auto *ctor = dyn_cast_or_null<ConstructorDecl>(UseDC)) {
7405- if (base && ctor->getImplicitSelfDecl () != base->getDecl ())
7406- return storageIsMutable (supportsMutation ());
7407- return StorageMutability::Initializable;
7407+ // If we're referencing 'self.', it's initializable.
7408+ if (!base ||
7409+ (*base && ctor->getImplicitSelfDecl () == (*base)->getDecl ()))
7410+ return StorageMutability::Initializable;
7411+
7412+ return storageIsMutable (supportsMutation ());
74087413 }
74097414 }
74107415
@@ -7462,17 +7467,18 @@ VarDecl::mutability(const DeclContext *UseDC,
74627467 getDeclContext ()->getSelfNominalTypeDecl ())
74637468 return StorageMutability::Immutable;
74647469
7465- if (base && CD->getImplicitSelfDecl () != base->getDecl ())
7466- return StorageMutability::Immutable;
7467-
74687470 // If this is a convenience initializer (i.e. one that calls
74697471 // self.init), then let properties are never mutable in it. They are
74707472 // only mutable in designated initializers.
74717473 auto initKindAndExpr = CD->getDelegatingOrChainedInitKind ();
74727474 if (initKindAndExpr.initKind == BodyInitKind::Delegating)
74737475 return StorageMutability::Immutable;
74747476
7475- return StorageMutability::Initializable;
7477+ // If we were given a base and it is 'self', it's initializable.
7478+ if (!base || (*base && CD->getImplicitSelfDecl () == (*base)->getDecl ()))
7479+ return StorageMutability::Initializable;
7480+
7481+ return StorageMutability::Immutable;
74767482 }
74777483
74787484 // If the 'let' has a value bound to it but has no PBD, then it is
0 commit comments