Skip to content

Commit d4ee434

Browse files
authored
Merge pull request #74056 from DougGregor/revert-immutable-let-changes-6.0
[6.0] Revert immutable let changes 6.0
2 parents 064604b + adba3c0 commit d4ee434

23 files changed

+149
-435
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) const {
5761-
switch (mutability(useDC)) {
5762-
case StorageMutability::Immutable:
5763-
return false;
5764-
case StorageMutability::Mutable:
5765-
case StorageMutability::Initializable:
5766-
return true;
5767-
}
5768-
}
5769-
5770-
/// Determine the mutability of this storage declaration when
5771-
/// accessed from a given declaration context.
5772-
StorageMutability mutability(
5773-
const DeclContext *useDC,
5774-
std::optional<const DeclRefExpr *> base = std::nullopt) 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-
std::optional<const DeclRefExpr *> base = std::nullopt) 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,15 +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) const {
5794-
switch (mutabilityInSwift(useDC)) {
5795-
case StorageMutability::Immutable:
5796-
return false;
5797-
case StorageMutability::Mutable:
5798-
case StorageMutability::Initializable:
5799-
return true;
5800-
}
5801-
}
5755+
bool isSettableInSwift(const DeclContext *UseDC,
5756+
const DeclRefExpr *base = nullptr) const;
58025757

58035758
/// Does this storage declaration have explicitly-defined accessors
58045759
/// written in the source?
@@ -6111,11 +6066,13 @@ class VarDecl : public AbstractStorageDecl {
61116066
/// precisely point to the variable type because of type aliases.
61126067
SourceRange getTypeSourceRangeForDiagnostics() const;
61136068

6114-
/// Determine the mutability of this variable declaration when
6115-
/// accessed from a given declaration context.
6116-
StorageMutability mutability(
6117-
const DeclContext *useDC,
6118-
std::optional<const DeclRefExpr *> base = std::nullopt) 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);

include/swift/Sema/ConstraintSystem.h

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,14 +2092,6 @@ struct ClosureIsolatedByPreconcurrency {
20922092
bool operator()(const ClosureExpr *expr) const;
20932093
};
20942094

2095-
/// Determine whether the given expression is part of the left-hand side
2096-
/// of an assignment expression.
2097-
struct IsInLeftHandSideOfAssignment {
2098-
ConstraintSystem &cs;
2099-
2100-
bool operator()(Expr *expr) const;
2101-
};
2102-
21032095
/// Describes the type produced when referencing a declaration.
21042096
struct DeclReferenceType {
21052097
/// The "opened" type, which is the type of the declaration where any
@@ -4412,7 +4404,7 @@ class ConstraintSystem {
44124404
/// \param wantInterfaceType Whether we want the interface type, if available.
44134405
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
44144406
DeclContext *UseDC,
4415-
ConstraintLocator *locator,
4407+
ConstraintLocator *memberLocator = nullptr,
44164408
bool wantInterfaceType = false,
44174409
bool adjustForPreconcurrency = true);
44184410

@@ -4434,7 +4426,7 @@ class ConstraintSystem {
44344426
getUnopenedTypeOfReference(
44354427
VarDecl *value, Type baseType, DeclContext *UseDC,
44364428
llvm::function_ref<Type(VarDecl *)> getType,
4437-
ConstraintLocator *locator,
4429+
ConstraintLocator *memberLocator = nullptr,
44384430
bool wantInterfaceType = false,
44394431
bool adjustForPreconcurrency = true,
44404432
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType =
@@ -4444,10 +4436,7 @@ class ConstraintSystem {
44444436
llvm::function_ref<bool(const ClosureExpr *)> isolatedByPreconcurrency =
44454437
[](const ClosureExpr *closure) {
44464438
return closure->isIsolatedByPreconcurrency();
4447-
},
4448-
llvm::function_ref<bool(Expr *)> isAssignTarget = [](Expr *) {
4449-
return false;
4450-
});
4439+
});
44514440

44524441
/// Given the opened type and a pile of information about a member reference,
44534442
/// determine the reference type of the member reference.

lib/AST/Decl.cpp

Lines changed: 26 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3091,36 +3091,6 @@ bool AbstractStorageDecl::isSetterMutating() const {
30913091
IsSetterMutatingRequest{const_cast<AbstractStorageDecl *>(this)}, {});
30923092
}
30933093

3094-
StorageMutability
3095-
AbstractStorageDecl::mutability(const DeclContext *useDC,
3096-
std::optional<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(
3113-
const DeclContext *useDC,
3114-
std::optional<const DeclRefExpr *> base
3115-
) const {
3116-
// TODO: Writing to an optional storage requirement is not supported in Swift.
3117-
if (getAttrs().hasAttribute<OptionalAttr>()) {
3118-
return StorageMutability::Immutable;
3119-
}
3120-
3121-
return mutability(useDC, base);
3122-
}
3123-
31243094
OpaqueReadOwnership AbstractStorageDecl::getOpaqueReadOwnership() const {
31253095
ASTContext &ctx = getASTContext();
31263096
return evaluateOrDefault(ctx.evaluator,
@@ -7291,42 +7261,32 @@ Type VarDecl::getTypeInContext() const {
72917261
return getDeclContext()->mapTypeIntoContext(getInterfaceType());
72927262
}
72937263

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-
73007264
/// Returns whether the var is settable in the specified context: this
73017265
/// is either because it is a stored var, because it has a custom setter, or
73027266
/// is a let member in an initializer.
7303-
StorageMutability
7304-
VarDecl::mutability(const DeclContext *UseDC,
7305-
std::optional<const DeclRefExpr *> base) const {
7267+
bool VarDecl::isSettable(const DeclContext *UseDC,
7268+
const DeclRefExpr *base) const {
73067269
// Parameters are settable or not depending on their ownership convention.
73077270
if (auto *PD = dyn_cast<ParamDecl>(this))
7308-
return storageIsMutable(!PD->isImmutableInFunctionBody());
7271+
return !PD->isImmutableInFunctionBody();
73097272

73107273
// If this is a 'var' decl, then we're settable if we have storage or a
73117274
// setter.
73127275
if (!isLet()) {
73137276
if (hasInitAccessor()) {
73147277
if (auto *ctor = dyn_cast_or_null<ConstructorDecl>(UseDC)) {
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());
7278+
if (base && ctor->getImplicitSelfDecl() != base->getDecl())
7279+
return supportsMutation();
7280+
return true;
73217281
}
73227282
}
73237283

7324-
return storageIsMutable(supportsMutation());
7284+
return supportsMutation();
73257285
}
73267286

73277287
// Static 'let's are always immutable.
73287288
if (isStatic()) {
7329-
return StorageMutability::Immutable;
7289+
return false;
73307290
}
73317291

73327292
//
@@ -7336,11 +7296,11 @@ VarDecl::mutability(const DeclContext *UseDC,
73367296

73377297
// Debugger expression 'let's are initialized through a side-channel.
73387298
if (isDebuggerVar())
7339-
return StorageMutability::Immutable;
7299+
return false;
73407300

73417301
// 'let's are only ever settable from a specific DeclContext.
73427302
if (UseDC == nullptr)
7343-
return StorageMutability::Immutable;
7303+
return false;
73447304

73457305
// 'let' properties in structs/classes are only ever settable in their
73467306
// designated initializer(s) or by init accessors.
@@ -7352,65 +7312,61 @@ VarDecl::mutability(const DeclContext *UseDC,
73527312
// Check whether this property is part of `initializes` list,
73537313
// and allow assignment/mutation if so. DI would be responsible
73547314
// for checking for re-assignment.
7355-
if (accessor->isInitAccessor() &&
7315+
return accessor->isInitAccessor() &&
73567316
llvm::is_contained(accessor->getInitializedProperties(),
7357-
const_cast<VarDecl *>(this)))
7358-
return StorageMutability::Initializable;
7359-
7360-
return StorageMutability::Immutable;
7317+
const_cast<VarDecl *>(this));
73617318
}
73627319

73637320
auto *CD = dyn_cast<ConstructorDecl>(UseDC);
7364-
if (!CD) return StorageMutability::Immutable;
7365-
7321+
if (!CD) return false;
7322+
73667323
auto *CDC = CD->getDeclContext();
73677324

73687325
// 'let' properties are not valid inside protocols.
73697326
if (CDC->getExtendedProtocolDecl())
7370-
return StorageMutability::Immutable;
7327+
return false;
73717328

73727329
// If this init is defined inside of the same type (or in an extension
73737330
// thereof) as the let property, then it is mutable.
73747331
if (CDC->getSelfNominalTypeDecl() !=
73757332
getDeclContext()->getSelfNominalTypeDecl())
7376-
return StorageMutability::Immutable;
7333+
return false;
7334+
7335+
if (base && CD->getImplicitSelfDecl() != base->getDecl())
7336+
return false;
73777337

73787338
// If this is a convenience initializer (i.e. one that calls
73797339
// self.init), then let properties are never mutable in it. They are
73807340
// only mutable in designated initializers.
73817341
auto initKindAndExpr = CD->getDelegatingOrChainedInitKind();
73827342
if (initKindAndExpr.initKind == BodyInitKind::Delegating)
7383-
return StorageMutability::Immutable;
7384-
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;
7343+
return false;
73887344

7389-
return StorageMutability::Immutable;
7345+
return true;
73907346
}
73917347

73927348
// If the 'let' has a value bound to it but has no PBD, then it is
73937349
// already initializedand not settable.
73947350
if (getParentPatternBinding() == nullptr)
7395-
return StorageMutability::Immutable;
7351+
return false;
73967352

73977353
// If the 'let' has an explicitly written initializer with a pattern binding,
73987354
// then it isn't settable.
73997355
if (isParentInitialized())
7400-
return StorageMutability::Immutable;
7356+
return false;
74017357

74027358
// Normal lets (e.g. globals) are only mutable in the context of the
74037359
// declaration. To handle top-level code properly, we look through
74047360
// the TopLevelCode decl on the use (if present) since the vardecl may be
74057361
// one level up.
74067362
if (getDeclContext() == UseDC)
7407-
return StorageMutability::Initializable;
7363+
return true;
74087364

74097365
if (isa<TopLevelCodeDecl>(UseDC) &&
74107366
getDeclContext() == UseDC->getParent())
7411-
return StorageMutability::Initializable;
7367+
return true;
74127368

7413-
return StorageMutability::Immutable;
7369+
return false;
74147370
}
74157371

74167372
bool VarDecl::isLazilyInitializedGlobal() const {

lib/SILGen/SILGenConcurrency.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,7 @@ bool SILGenFunction::unsafelyInheritsExecutor() {
648648

649649
void ExecutorBreadcrumb::emit(SILGenFunction &SGF, SILLocation loc) {
650650
if (mustReturnToExecutor) {
651-
assert(SGF.ExpectedExecutor || SGF.unsafelyInheritsExecutor() ||
652-
SGF.isCtorWithHopsInjectedByDefiniteInit());
651+
assert(SGF.ExpectedExecutor || SGF.unsafelyInheritsExecutor());
653652
if (auto executor = SGF.ExpectedExecutor)
654653
SGF.B.createHopToExecutor(
655654
RegularLocation::getDebugOnlyLocation(loc, SGF.getModule()), executor,

lib/SILGen/SILGenConstructor.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -618,19 +618,6 @@ static bool ctorHopsInjectedByDefiniteInit(ConstructorDecl *ctor,
618618
}
619619
}
620620

621-
bool SILGenFunction::isCtorWithHopsInjectedByDefiniteInit() {
622-
auto declRef = F.getDeclRef();
623-
if (!declRef || !declRef.isConstructor())
624-
return false;
625-
626-
auto ctor = dyn_cast_or_null<ConstructorDecl>(declRef.getDecl());
627-
if (!ctor)
628-
return false;
629-
630-
auto isolation = getActorIsolation(ctor);
631-
return ctorHopsInjectedByDefiniteInit(ctor, isolation);
632-
}
633-
634621
void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
635622
MagicFunctionName = SILGenModule::getMagicFunctionName(ctor);
636623

lib/SILGen/SILGenFunction.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
820820
/// the fields.
821821
void emitDeallocatingMoveOnlyDestructor(DestructorDecl *dd);
822822

823-
/// Whether we are inside a constructor whose hops are injected by
824-
/// definite initialization.
825-
bool isCtorWithHopsInjectedByDefiniteInit();
826-
827823
/// Generates code for a struct constructor.
828824
/// This allocates the new 'self' value, emits the
829825
/// body code, then returns the final initialized 'self'.

0 commit comments

Comments
 (0)