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