@@ -3091,6 +3091,34 @@ bool AbstractStorageDecl::isSetterMutating() const {
3091
3091
IsSetterMutatingRequest{const_cast <AbstractStorageDecl *>(this )}, {});
3092
3092
}
3093
3093
3094
+ StorageMutability
3095
+ AbstractStorageDecl::mutability (const DeclContext *useDC,
3096
+ const DeclRefExpr *base) const {
3097
+ if (auto vd = dyn_cast<VarDecl>(this ))
3098
+ return vd->mutability (useDC, base);
3099
+
3100
+ auto sd = cast<SubscriptDecl>(this );
3101
+ return sd->supportsMutation () ? StorageMutability::Mutable
3102
+ : StorageMutability::Immutable;
3103
+ }
3104
+
3105
+ // / Determine the mutability of this storage declaration when
3106
+ // / accessed from a given declaration context in Swift.
3107
+ // /
3108
+ // / This method differs only from 'mutability()' in its handling of
3109
+ // / 'optional' storage requirements, which lack support for direct
3110
+ // / writes in Swift.
3111
+ StorageMutability
3112
+ AbstractStorageDecl::mutabilityInSwift (const DeclContext *useDC,
3113
+ const DeclRefExpr *base) const {
3114
+ // TODO: Writing to an optional storage requirement is not supported in Swift.
3115
+ if (getAttrs ().hasAttribute <OptionalAttr>()) {
3116
+ return StorageMutability::Immutable;
3117
+ }
3118
+
3119
+ return mutability (useDC, base);
3120
+ }
3121
+
3094
3122
OpaqueReadOwnership AbstractStorageDecl::getOpaqueReadOwnership () const {
3095
3123
ASTContext &ctx = getASTContext ();
3096
3124
return evaluateOrDefault (ctx.evaluator ,
@@ -7263,32 +7291,39 @@ Type VarDecl::getTypeInContext() const {
7263
7291
return getDeclContext ()->mapTypeIntoContext (getInterfaceType ());
7264
7292
}
7265
7293
7294
+ // / Translate an "is mutable" bit into a StorageMutability value.
7295
+ static StorageMutability storageIsMutable (bool isMutable) {
7296
+ return isMutable ? StorageMutability::Mutable
7297
+ : StorageMutability::Immutable;
7298
+ }
7299
+
7266
7300
// / Returns whether the var is settable in the specified context: this
7267
7301
// / is either because it is a stored var, because it has a custom setter, or
7268
7302
// / is a let member in an initializer.
7269
- bool VarDecl::isSettable (const DeclContext *UseDC,
7270
- const DeclRefExpr *base) const {
7303
+ StorageMutability
7304
+ VarDecl::mutability (const DeclContext *UseDC,
7305
+ const DeclRefExpr *base) const {
7271
7306
// Parameters are settable or not depending on their ownership convention.
7272
7307
if (auto *PD = dyn_cast<ParamDecl>(this ))
7273
- return !PD->isImmutableInFunctionBody ();
7308
+ return storageIsMutable ( !PD->isImmutableInFunctionBody () );
7274
7309
7275
7310
// If this is a 'var' decl, then we're settable if we have storage or a
7276
7311
// setter.
7277
7312
if (!isLet ()) {
7278
7313
if (hasInitAccessor ()) {
7279
7314
if (auto *ctor = dyn_cast_or_null<ConstructorDecl>(UseDC)) {
7280
7315
if (base && ctor->getImplicitSelfDecl () != base->getDecl ())
7281
- return supportsMutation ();
7282
- return true ;
7316
+ return storageIsMutable ( supportsMutation () );
7317
+ return StorageMutability::Initializable ;
7283
7318
}
7284
7319
}
7285
7320
7286
- return supportsMutation ();
7321
+ return storageIsMutable ( supportsMutation () );
7287
7322
}
7288
7323
7289
7324
// Static 'let's are always immutable.
7290
7325
if (isStatic ()) {
7291
- return false ;
7326
+ return StorageMutability::Immutable ;
7292
7327
}
7293
7328
7294
7329
//
@@ -7298,11 +7333,11 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
7298
7333
7299
7334
// Debugger expression 'let's are initialized through a side-channel.
7300
7335
if (isDebuggerVar ())
7301
- return false ;
7336
+ return StorageMutability::Immutable ;
7302
7337
7303
7338
// 'let's are only ever settable from a specific DeclContext.
7304
7339
if (UseDC == nullptr )
7305
- return false ;
7340
+ return StorageMutability::Immutable ;
7306
7341
7307
7342
// 'let' properties in structs/classes are only ever settable in their
7308
7343
// designated initializer(s) or by init accessors.
@@ -7314,61 +7349,64 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
7314
7349
// Check whether this property is part of `initializes` list,
7315
7350
// and allow assignment/mutation if so. DI would be responsible
7316
7351
// for checking for re-assignment.
7317
- return accessor->isInitAccessor () &&
7352
+ if ( accessor->isInitAccessor () &&
7318
7353
llvm::is_contained (accessor->getInitializedProperties (),
7319
- const_cast <VarDecl *>(this ));
7354
+ const_cast <VarDecl *>(this )))
7355
+ return StorageMutability::Initializable;
7356
+
7357
+ return StorageMutability::Immutable;
7320
7358
}
7321
7359
7322
7360
auto *CD = dyn_cast<ConstructorDecl>(UseDC);
7323
- if (!CD) return false ;
7324
-
7361
+ if (!CD) return StorageMutability::Immutable ;
7362
+
7325
7363
auto *CDC = CD->getDeclContext ();
7326
7364
7327
7365
// 'let' properties are not valid inside protocols.
7328
7366
if (CDC->getExtendedProtocolDecl ())
7329
- return false ;
7367
+ return StorageMutability::Immutable ;
7330
7368
7331
7369
// If this init is defined inside of the same type (or in an extension
7332
7370
// thereof) as the let property, then it is mutable.
7333
7371
if (CDC->getSelfNominalTypeDecl () !=
7334
7372
getDeclContext ()->getSelfNominalTypeDecl ())
7335
- return false ;
7373
+ return StorageMutability::Immutable ;
7336
7374
7337
7375
if (base && CD->getImplicitSelfDecl () != base->getDecl ())
7338
- return false ;
7376
+ return StorageMutability::Immutable ;
7339
7377
7340
7378
// If this is a convenience initializer (i.e. one that calls
7341
7379
// self.init), then let properties are never mutable in it. They are
7342
7380
// only mutable in designated initializers.
7343
7381
auto initKindAndExpr = CD->getDelegatingOrChainedInitKind ();
7344
7382
if (initKindAndExpr.initKind == BodyInitKind::Delegating)
7345
- return false ;
7383
+ return StorageMutability::Immutable ;
7346
7384
7347
- return true ;
7385
+ return StorageMutability::Initializable ;
7348
7386
}
7349
7387
7350
7388
// If the 'let' has a value bound to it but has no PBD, then it is
7351
7389
// already initializedand not settable.
7352
7390
if (getParentPatternBinding () == nullptr )
7353
- return false ;
7391
+ return StorageMutability::Immutable ;
7354
7392
7355
7393
// If the 'let' has an explicitly written initializer with a pattern binding,
7356
7394
// then it isn't settable.
7357
7395
if (isParentInitialized ())
7358
- return false ;
7396
+ return StorageMutability::Immutable ;
7359
7397
7360
7398
// Normal lets (e.g. globals) are only mutable in the context of the
7361
7399
// declaration. To handle top-level code properly, we look through
7362
7400
// the TopLevelCode decl on the use (if present) since the vardecl may be
7363
7401
// one level up.
7364
7402
if (getDeclContext () == UseDC)
7365
- return true ;
7403
+ return StorageMutability::Initializable ;
7366
7404
7367
7405
if (isa<TopLevelCodeDecl>(UseDC) &&
7368
7406
getDeclContext () == UseDC->getParent ())
7369
- return true ;
7407
+ return StorageMutability::Initializable ;
7370
7408
7371
- return false ;
7409
+ return StorageMutability::Immutable ;
7372
7410
}
7373
7411
7374
7412
bool VarDecl::isLazilyInitializedGlobal () const {
0 commit comments