@@ -3087,7 +3087,7 @@ bool AbstractStorageDecl::isSetterMutating() const {
3087
3087
3088
3088
StorageMutability
3089
3089
AbstractStorageDecl::mutability (const DeclContext *useDC,
3090
- const DeclRefExpr *base) const {
3090
+ std::optional< const DeclRefExpr *> base ) const {
3091
3091
if (auto vd = dyn_cast<VarDecl>(this ))
3092
3092
return vd->mutability (useDC, base);
3093
3093
@@ -3103,8 +3103,10 @@ AbstractStorageDecl::mutability(const DeclContext *useDC,
3103
3103
// / 'optional' storage requirements, which lack support for direct
3104
3104
// / writes in Swift.
3105
3105
StorageMutability
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 {
3108
3110
// TODO: Writing to an optional storage requirement is not supported in Swift.
3109
3111
if (getAttrs ().hasAttribute <OptionalAttr>()) {
3110
3112
return StorageMutability::Immutable;
@@ -7392,7 +7394,7 @@ static StorageMutability storageIsMutable(bool isMutable) {
7392
7394
// / is a let member in an initializer.
7393
7395
StorageMutability
7394
7396
VarDecl::mutability (const DeclContext *UseDC,
7395
- const DeclRefExpr *base) const {
7397
+ std::optional< const DeclRefExpr *> base) const {
7396
7398
// Parameters are settable or not depending on their ownership convention.
7397
7399
if (auto *PD = dyn_cast<ParamDecl>(this ))
7398
7400
return storageIsMutable (!PD->isImmutableInFunctionBody ());
@@ -7402,9 +7404,12 @@ VarDecl::mutability(const DeclContext *UseDC,
7402
7404
if (!isLet ()) {
7403
7405
if (hasInitAccessor ()) {
7404
7406
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 ());
7408
7413
}
7409
7414
}
7410
7415
@@ -7462,17 +7467,18 @@ VarDecl::mutability(const DeclContext *UseDC,
7462
7467
getDeclContext ()->getSelfNominalTypeDecl ())
7463
7468
return StorageMutability::Immutable;
7464
7469
7465
- if (base && CD->getImplicitSelfDecl () != base->getDecl ())
7466
- return StorageMutability::Immutable;
7467
-
7468
7470
// If this is a convenience initializer (i.e. one that calls
7469
7471
// self.init), then let properties are never mutable in it. They are
7470
7472
// only mutable in designated initializers.
7471
7473
auto initKindAndExpr = CD->getDelegatingOrChainedInitKind ();
7472
7474
if (initKindAndExpr.initKind == BodyInitKind::Delegating)
7473
7475
return StorageMutability::Immutable;
7474
7476
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;
7476
7482
}
7477
7483
7478
7484
// If the 'let' has a value bound to it but has no PBD, then it is
0 commit comments