Skip to content

Commit 3f98a9f

Browse files
committed
Revert "Generalize AbstractStorageDecl::isSettable() to return a three-state value"
This reverts commit a34a2d3.
1 parent 13bdd7b commit 3f98a9f

File tree

2 files changed

+54
-115
lines changed

2 files changed

+54
-115
lines changed

include/swift/AST/Decl.h

Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5571,21 +5571,6 @@ class BuiltinTupleDecl final : public NominalTypeDecl {
55715571
}
55725572
};
55735573

5574-
/// Describes whether a particular storage declaration is mutable.
5575-
enum class StorageMutability {
5576-
/// The storage is immutable, meaning that it can neither be assigned
5577-
/// to nor passed inout.
5578-
Immutable,
5579-
5580-
/// The storage is mutable, meaning that it can be assigned and pased
5581-
/// inout.
5582-
Mutable,
5583-
5584-
/// The storage is immutable, but can be asigned for the purposes of
5585-
/// initialization.
5586-
Initializable
5587-
};
5588-
55895574
/// AbstractStorageDecl - This is the common superclass for VarDecl and
55905575
/// SubscriptDecl, representing potentially settable memory locations.
55915576
class AbstractStorageDecl : public ValueDecl {
@@ -5757,31 +5742,8 @@ class AbstractStorageDecl : public ValueDecl {
57575742
/// Determine whether references to this storage declaration may appear
57585743
/// on the left-hand side of an assignment, as the operand of a
57595744
/// `&` or 'inout' operator, or as a component in a writable key path.
5760-
bool isSettable(const DeclContext *useDC,
5761-
const DeclRefExpr *base = nullptr) const {
5762-
switch (mutability(useDC, base)) {
5763-
case StorageMutability::Immutable:
5764-
return false;
5765-
case StorageMutability::Mutable:
5766-
case StorageMutability::Initializable:
5767-
return true;
5768-
}
5769-
}
5770-
5771-
/// Determine the mutability of this storage declaration when
5772-
/// accessed from a given declaration context.
5773-
StorageMutability mutability(const DeclContext *useDC,
5774-
const DeclRefExpr *base = nullptr) const;
5775-
5776-
/// Determine the mutability of this storage declaration when
5777-
/// accessed from a given declaration context in Swift.
5778-
///
5779-
/// This method differs only from 'mutability()' in its handling of
5780-
/// 'optional' storage requirements, which lack support for direct
5781-
/// writes in Swift.
5782-
StorageMutability mutabilityInSwift(
5783-
const DeclContext *useDC,
5784-
const DeclRefExpr *base = nullptr) const;
5745+
bool isSettable(const DeclContext *UseDC,
5746+
const DeclRefExpr *base = nullptr) const;
57855747

57865748
/// Determine whether references to this storage declaration in Swift may
57875749
/// appear on the left-hand side of an assignment, as the operand of a
@@ -5790,16 +5752,8 @@ class AbstractStorageDecl : public ValueDecl {
57905752
/// This method is equivalent to \c isSettable with the exception of
57915753
/// 'optional' storage requirements, which lack support for direct writes
57925754
/// in Swift.
5793-
bool isSettableInSwift(const DeclContext *useDC,
5794-
const DeclRefExpr *base = nullptr) const {
5795-
switch (mutabilityInSwift(useDC, base)) {
5796-
case StorageMutability::Immutable:
5797-
return false;
5798-
case StorageMutability::Mutable:
5799-
case StorageMutability::Initializable:
5800-
return true;
5801-
}
5802-
}
5755+
bool isSettableInSwift(const DeclContext *UseDC,
5756+
const DeclRefExpr *base = nullptr) const;
58035757

58045758
/// Does this storage declaration have explicitly-defined accessors
58055759
/// written in the source?
@@ -6112,10 +6066,13 @@ class VarDecl : public AbstractStorageDecl {
61126066
/// precisely point to the variable type because of type aliases.
61136067
SourceRange getTypeSourceRangeForDiagnostics() const;
61146068

6115-
/// Determine the mutability of this variable declaration when
6116-
/// accessed from a given declaration context.
6117-
StorageMutability mutability(const DeclContext *useDC,
6118-
const DeclRefExpr *base = nullptr) const;
6069+
/// Returns whether the var is settable in the specified context: this
6070+
/// is either because it is a stored var, because it has a custom setter, or
6071+
/// is a let member in an initializer.
6072+
///
6073+
/// Pass a null context and null base to check if it's always settable.
6074+
bool isSettable(const DeclContext *UseDC,
6075+
const DeclRefExpr *base = nullptr) const;
61196076

61206077
/// Return the parent pattern binding that may provide an initializer for this
61216078
/// VarDecl. This returns null if there is none associated with the VarDecl.
@@ -9343,6 +9300,26 @@ findGenericParameterReferences(const ValueDecl *value, CanGenericSignature sig,
93439300
bool treatNonResultCovarianceAsInvariant,
93449301
std::optional<unsigned> skipParamIndex);
93459302

9303+
inline bool AbstractStorageDecl::isSettable(const DeclContext *UseDC,
9304+
const DeclRefExpr *base) const {
9305+
if (auto vd = dyn_cast<VarDecl>(this))
9306+
return vd->isSettable(UseDC, base);
9307+
9308+
auto sd = cast<SubscriptDecl>(this);
9309+
return sd->supportsMutation();
9310+
}
9311+
9312+
inline bool
9313+
AbstractStorageDecl::isSettableInSwift(const DeclContext *UseDC,
9314+
const DeclRefExpr *base) const {
9315+
// TODO: Writing to an optional storage requirement is not supported in Swift.
9316+
if (getAttrs().hasAttribute<OptionalAttr>()) {
9317+
return false;
9318+
}
9319+
9320+
return isSettable(UseDC, base);
9321+
}
9322+
93469323
inline void
93479324
AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) {
93489325
Accessors.setInt(accessLevel);

lib/AST/Decl.cpp

Lines changed: 23 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3091,34 +3091,6 @@ 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-
31223094
OpaqueReadOwnership AbstractStorageDecl::getOpaqueReadOwnership() const {
31233095
ASTContext &ctx = getASTContext();
31243096
return evaluateOrDefault(ctx.evaluator,
@@ -7289,39 +7261,32 @@ Type VarDecl::getTypeInContext() const {
72897261
return getDeclContext()->mapTypeIntoContext(getInterfaceType());
72907262
}
72917263

7292-
/// Translate an "is mutable" bit into a StorageMutability value.
7293-
static StorageMutability storageIsMutable(bool isMutable) {
7294-
return isMutable ? StorageMutability::Mutable
7295-
: StorageMutability::Immutable;
7296-
}
7297-
72987264
/// Returns whether the var is settable in the specified context: this
72997265
/// is either because it is a stored var, because it has a custom setter, or
73007266
/// is a let member in an initializer.
7301-
StorageMutability
7302-
VarDecl::mutability(const DeclContext *UseDC,
7303-
const DeclRefExpr *base) const {
7267+
bool VarDecl::isSettable(const DeclContext *UseDC,
7268+
const DeclRefExpr *base) const {
73047269
// Parameters are settable or not depending on their ownership convention.
73057270
if (auto *PD = dyn_cast<ParamDecl>(this))
7306-
return storageIsMutable(!PD->isImmutableInFunctionBody());
7271+
return !PD->isImmutableInFunctionBody();
73077272

73087273
// If this is a 'var' decl, then we're settable if we have storage or a
73097274
// setter.
73107275
if (!isLet()) {
73117276
if (hasInitAccessor()) {
73127277
if (auto *ctor = dyn_cast_or_null<ConstructorDecl>(UseDC)) {
73137278
if (base && ctor->getImplicitSelfDecl() != base->getDecl())
7314-
return storageIsMutable(supportsMutation());
7315-
return StorageMutability::Initializable;
7279+
return supportsMutation();
7280+
return true;
73167281
}
73177282
}
73187283

7319-
return storageIsMutable(supportsMutation());
7284+
return supportsMutation();
73207285
}
73217286

73227287
// Static 'let's are always immutable.
73237288
if (isStatic()) {
7324-
return StorageMutability::Immutable;
7289+
return false;
73257290
}
73267291

73277292
//
@@ -7331,11 +7296,11 @@ VarDecl::mutability(const DeclContext *UseDC,
73317296

73327297
// Debugger expression 'let's are initialized through a side-channel.
73337298
if (isDebuggerVar())
7334-
return StorageMutability::Immutable;
7299+
return false;
73357300

73367301
// 'let's are only ever settable from a specific DeclContext.
73377302
if (UseDC == nullptr)
7338-
return StorageMutability::Immutable;
7303+
return false;
73397304

73407305
// 'let' properties in structs/classes are only ever settable in their
73417306
// designated initializer(s) or by init accessors.
@@ -7347,64 +7312,61 @@ VarDecl::mutability(const DeclContext *UseDC,
73477312
// Check whether this property is part of `initializes` list,
73487313
// and allow assignment/mutation if so. DI would be responsible
73497314
// for checking for re-assignment.
7350-
if (accessor->isInitAccessor() &&
7315+
return accessor->isInitAccessor() &&
73517316
llvm::is_contained(accessor->getInitializedProperties(),
7352-
const_cast<VarDecl *>(this)))
7353-
return StorageMutability::Initializable;
7354-
7355-
return StorageMutability::Immutable;
7317+
const_cast<VarDecl *>(this));
73567318
}
73577319

73587320
auto *CD = dyn_cast<ConstructorDecl>(UseDC);
7359-
if (!CD) return StorageMutability::Immutable;
7360-
7321+
if (!CD) return false;
7322+
73617323
auto *CDC = CD->getDeclContext();
73627324

73637325
// 'let' properties are not valid inside protocols.
73647326
if (CDC->getExtendedProtocolDecl())
7365-
return StorageMutability::Immutable;
7327+
return false;
73667328

73677329
// If this init is defined inside of the same type (or in an extension
73687330
// thereof) as the let property, then it is mutable.
73697331
if (CDC->getSelfNominalTypeDecl() !=
73707332
getDeclContext()->getSelfNominalTypeDecl())
7371-
return StorageMutability::Immutable;
7333+
return false;
73727334

73737335
if (base && CD->getImplicitSelfDecl() != base->getDecl())
7374-
return StorageMutability::Immutable;
7336+
return false;
73757337

73767338
// If this is a convenience initializer (i.e. one that calls
73777339
// self.init), then let properties are never mutable in it. They are
73787340
// only mutable in designated initializers.
73797341
auto initKindAndExpr = CD->getDelegatingOrChainedInitKind();
73807342
if (initKindAndExpr.initKind == BodyInitKind::Delegating)
7381-
return StorageMutability::Immutable;
7343+
return false;
73827344

7383-
return StorageMutability::Initializable;
7345+
return true;
73847346
}
73857347

73867348
// If the 'let' has a value bound to it but has no PBD, then it is
73877349
// already initializedand not settable.
73887350
if (getParentPatternBinding() == nullptr)
7389-
return StorageMutability::Immutable;
7351+
return false;
73907352

73917353
// If the 'let' has an explicitly written initializer with a pattern binding,
73927354
// then it isn't settable.
73937355
if (isParentInitialized())
7394-
return StorageMutability::Immutable;
7356+
return false;
73957357

73967358
// Normal lets (e.g. globals) are only mutable in the context of the
73977359
// declaration. To handle top-level code properly, we look through
73987360
// the TopLevelCode decl on the use (if present) since the vardecl may be
73997361
// one level up.
74007362
if (getDeclContext() == UseDC)
7401-
return StorageMutability::Initializable;
7363+
return true;
74027364

74037365
if (isa<TopLevelCodeDecl>(UseDC) &&
74047366
getDeclContext() == UseDC->getParent())
7405-
return StorageMutability::Initializable;
7367+
return true;
74067368

7407-
return StorageMutability::Immutable;
7369+
return false;
74087370
}
74097371

74107372
bool VarDecl::isLazilyInitializedGlobal() const {

0 commit comments

Comments
 (0)