@@ -3091,6 +3091,34 @@ bool AbstractStorageDecl::isSetterMutating() const {
30913091 IsSetterMutatingRequest{const_cast <AbstractStorageDecl *>(this )}, {});
30923092}
30933093
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+
30943122OpaqueReadOwnership AbstractStorageDecl::getOpaqueReadOwnership () const {
30953123 ASTContext &ctx = getASTContext ();
30963124 return evaluateOrDefault (ctx.evaluator ,
@@ -7263,32 +7291,39 @@ Type VarDecl::getTypeInContext() const {
72637291 return getDeclContext ()->mapTypeIntoContext (getInterfaceType ());
72647292}
72657293
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+
72667300// / Returns whether the var is settable in the specified context: this
72677301// / is either because it is a stored var, because it has a custom setter, or
72687302// / 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 {
72717306 // Parameters are settable or not depending on their ownership convention.
72727307 if (auto *PD = dyn_cast<ParamDecl>(this ))
7273- return !PD->isImmutableInFunctionBody ();
7308+ return storageIsMutable ( !PD->isImmutableInFunctionBody () );
72747309
72757310 // If this is a 'var' decl, then we're settable if we have storage or a
72767311 // setter.
72777312 if (!isLet ()) {
72787313 if (hasInitAccessor ()) {
72797314 if (auto *ctor = dyn_cast_or_null<ConstructorDecl>(UseDC)) {
72807315 if (base && ctor->getImplicitSelfDecl () != base->getDecl ())
7281- return supportsMutation ();
7282- return true ;
7316+ return storageIsMutable ( supportsMutation () );
7317+ return StorageMutability::Initializable ;
72837318 }
72847319 }
72857320
7286- return supportsMutation ();
7321+ return storageIsMutable ( supportsMutation () );
72877322 }
72887323
72897324 // Static 'let's are always immutable.
72907325 if (isStatic ()) {
7291- return false ;
7326+ return StorageMutability::Immutable ;
72927327 }
72937328
72947329 //
@@ -7298,11 +7333,11 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
72987333
72997334 // Debugger expression 'let's are initialized through a side-channel.
73007335 if (isDebuggerVar ())
7301- return false ;
7336+ return StorageMutability::Immutable ;
73027337
73037338 // 'let's are only ever settable from a specific DeclContext.
73047339 if (UseDC == nullptr )
7305- return false ;
7340+ return StorageMutability::Immutable ;
73067341
73077342 // 'let' properties in structs/classes are only ever settable in their
73087343 // designated initializer(s) or by init accessors.
@@ -7314,61 +7349,64 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
73147349 // Check whether this property is part of `initializes` list,
73157350 // and allow assignment/mutation if so. DI would be responsible
73167351 // for checking for re-assignment.
7317- return accessor->isInitAccessor () &&
7352+ if ( accessor->isInitAccessor () &&
73187353 llvm::is_contained (accessor->getInitializedProperties (),
7319- const_cast <VarDecl *>(this ));
7354+ const_cast <VarDecl *>(this )))
7355+ return StorageMutability::Initializable;
7356+
7357+ return StorageMutability::Immutable;
73207358 }
73217359
73227360 auto *CD = dyn_cast<ConstructorDecl>(UseDC);
7323- if (!CD) return false ;
7324-
7361+ if (!CD) return StorageMutability::Immutable ;
7362+
73257363 auto *CDC = CD->getDeclContext ();
73267364
73277365 // 'let' properties are not valid inside protocols.
73287366 if (CDC->getExtendedProtocolDecl ())
7329- return false ;
7367+ return StorageMutability::Immutable ;
73307368
73317369 // If this init is defined inside of the same type (or in an extension
73327370 // thereof) as the let property, then it is mutable.
73337371 if (CDC->getSelfNominalTypeDecl () !=
73347372 getDeclContext ()->getSelfNominalTypeDecl ())
7335- return false ;
7373+ return StorageMutability::Immutable ;
73367374
73377375 if (base && CD->getImplicitSelfDecl () != base->getDecl ())
7338- return false ;
7376+ return StorageMutability::Immutable ;
73397377
73407378 // If this is a convenience initializer (i.e. one that calls
73417379 // self.init), then let properties are never mutable in it. They are
73427380 // only mutable in designated initializers.
73437381 auto initKindAndExpr = CD->getDelegatingOrChainedInitKind ();
73447382 if (initKindAndExpr.initKind == BodyInitKind::Delegating)
7345- return false ;
7383+ return StorageMutability::Immutable ;
73467384
7347- return true ;
7385+ return StorageMutability::Initializable ;
73487386 }
73497387
73507388 // If the 'let' has a value bound to it but has no PBD, then it is
73517389 // already initializedand not settable.
73527390 if (getParentPatternBinding () == nullptr )
7353- return false ;
7391+ return StorageMutability::Immutable ;
73547392
73557393 // If the 'let' has an explicitly written initializer with a pattern binding,
73567394 // then it isn't settable.
73577395 if (isParentInitialized ())
7358- return false ;
7396+ return StorageMutability::Immutable ;
73597397
73607398 // Normal lets (e.g. globals) are only mutable in the context of the
73617399 // declaration. To handle top-level code properly, we look through
73627400 // the TopLevelCode decl on the use (if present) since the vardecl may be
73637401 // one level up.
73647402 if (getDeclContext () == UseDC)
7365- return true ;
7403+ return StorageMutability::Initializable ;
73667404
73677405 if (isa<TopLevelCodeDecl>(UseDC) &&
73687406 getDeclContext () == UseDC->getParent ())
7369- return true ;
7407+ return StorageMutability::Initializable ;
73707408
7371- return false ;
7409+ return StorageMutability::Immutable ;
73727410}
73737411
73747412bool VarDecl::isLazilyInitializedGlobal () const {
0 commit comments