@@ -3093,7 +3093,7 @@ bool AbstractStorageDecl::isSetterMutating() const {
3093
3093
3094
3094
StorageMutability
3095
3095
AbstractStorageDecl::mutability (const DeclContext *useDC,
3096
- const DeclRefExpr *base) const {
3096
+ std::optional< const DeclRefExpr *> base ) const {
3097
3097
if (auto vd = dyn_cast<VarDecl>(this ))
3098
3098
return vd->mutability (useDC, base);
3099
3099
@@ -3109,8 +3109,10 @@ AbstractStorageDecl::mutability(const DeclContext *useDC,
3109
3109
// / 'optional' storage requirements, which lack support for direct
3110
3110
// / writes in Swift.
3111
3111
StorageMutability
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 {
3114
3116
// TODO: Writing to an optional storage requirement is not supported in Swift.
3115
3117
if (getAttrs ().hasAttribute <OptionalAttr>()) {
3116
3118
return StorageMutability::Immutable;
@@ -7312,7 +7314,7 @@ static StorageMutability storageIsMutable(bool isMutable) {
7312
7314
// / is a let member in an initializer.
7313
7315
StorageMutability
7314
7316
VarDecl::mutability (const DeclContext *UseDC,
7315
- const DeclRefExpr *base) const {
7317
+ std::optional< const DeclRefExpr *> base) const {
7316
7318
// Parameters are settable or not depending on their ownership convention.
7317
7319
if (auto *PD = dyn_cast<ParamDecl>(this ))
7318
7320
return storageIsMutable (!PD->isImmutableInFunctionBody ());
@@ -7322,9 +7324,12 @@ VarDecl::mutability(const DeclContext *UseDC,
7322
7324
if (!isLet ()) {
7323
7325
if (hasInitAccessor ()) {
7324
7326
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 ());
7328
7333
}
7329
7334
}
7330
7335
@@ -7382,17 +7387,18 @@ VarDecl::mutability(const DeclContext *UseDC,
7382
7387
getDeclContext ()->getSelfNominalTypeDecl ())
7383
7388
return StorageMutability::Immutable;
7384
7389
7385
- if (base && CD->getImplicitSelfDecl () != base->getDecl ())
7386
- return StorageMutability::Immutable;
7387
-
7388
7390
// If this is a convenience initializer (i.e. one that calls
7389
7391
// self.init), then let properties are never mutable in it. They are
7390
7392
// only mutable in designated initializers.
7391
7393
auto initKindAndExpr = CD->getDelegatingOrChainedInitKind ();
7392
7394
if (initKindAndExpr.initKind == BodyInitKind::Delegating)
7393
7395
return StorageMutability::Immutable;
7394
7396
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;
7396
7402
}
7397
7403
7398
7404
// If the 'let' has a value bound to it but has no PBD, then it is
0 commit comments