@@ -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;
@@ -7300,7 +7302,7 @@ static StorageMutability storageIsMutable(bool isMutable) {
7300
7302
// / is a let member in an initializer.
7301
7303
StorageMutability
7302
7304
VarDecl::mutability (const DeclContext *UseDC,
7303
- const DeclRefExpr *base) const {
7305
+ std::optional< const DeclRefExpr *> base) const {
7304
7306
// Parameters are settable or not depending on their ownership convention.
7305
7307
if (auto *PD = dyn_cast<ParamDecl>(this ))
7306
7308
return storageIsMutable (!PD->isImmutableInFunctionBody ());
@@ -7310,9 +7312,12 @@ VarDecl::mutability(const DeclContext *UseDC,
7310
7312
if (!isLet ()) {
7311
7313
if (hasInitAccessor ()) {
7312
7314
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 ());
7316
7321
}
7317
7322
}
7318
7323
@@ -7370,17 +7375,18 @@ VarDecl::mutability(const DeclContext *UseDC,
7370
7375
getDeclContext ()->getSelfNominalTypeDecl ())
7371
7376
return StorageMutability::Immutable;
7372
7377
7373
- if (base && CD->getImplicitSelfDecl () != base->getDecl ())
7374
- return StorageMutability::Immutable;
7375
-
7376
7378
// If this is a convenience initializer (i.e. one that calls
7377
7379
// self.init), then let properties are never mutable in it. They are
7378
7380
// only mutable in designated initializers.
7379
7381
auto initKindAndExpr = CD->getDelegatingOrChainedInitKind ();
7380
7382
if (initKindAndExpr.initKind == BodyInitKind::Delegating)
7381
7383
return StorageMutability::Immutable;
7382
7384
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;
7384
7390
}
7385
7391
7386
7392
// If the 'let' has a value bound to it but has no PBD, then it is
0 commit comments