@@ -830,45 +830,42 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
830
830
}
831
831
}
832
832
833
+ // If the base is not 'self', default get access to nonmutating and set access to mutating.
834
+ bool getterMutatesBase = selfDecl && storage->isGetterMutating ();
835
+ bool setterMutatesBase = !selfDecl || storage->isSetterMutating ();
836
+ // If we're not accessing via a property wrapper, we don't need to adjust
837
+ // the mutability.
838
+ if (target == TargetImpl::Wrapper || target == TargetImpl::WrapperStorage) {
839
+ auto var = cast<VarDecl>(accessor->getStorage ());
840
+ auto mutability = var->getPropertyWrapperMutability ();
841
+ // Only adjust mutability if it's possible to mutate the base.
842
+ if (mutability && !var->isStatic () &&
843
+ !(selfDecl && selfTypeForAccess->hasReferenceSemantics ())) {
844
+ getterMutatesBase = (mutability->Getter == PropertyWrapperMutability::Mutating);
845
+ setterMutatesBase = (mutability->Setter == PropertyWrapperMutability::Mutating);
846
+ }
847
+ }
848
+
849
+ // If the accessor is mutating, then the base should be referred as an l-value
850
+ bool isBaseLValue = (getterMutatesBase && isUsedForGetAccess) ||
851
+ (setterMutatesBase && isUsedForSetAccess);
852
+
833
853
if (!selfDecl) {
834
854
assert (target != TargetImpl::Super);
835
855
auto *storageDRE = new (ctx) DeclRefExpr (storage, DeclNameLoc (),
836
856
/* IsImplicit=*/ true , semantics);
837
857
auto type = storage->getValueInterfaceType ().subst (subs);
838
- if (isLValue )
858
+ if (isBaseLValue )
839
859
type = LValueType::get (type);
840
860
storageDRE->setType (type);
841
861
842
862
return finish (storageDRE);
843
863
}
844
864
845
865
// Build self
846
-
847
- bool isGetterMutating = storage->isGetterMutating ();
848
- bool isSetterMutating = storage->isSetterMutating ();
849
- // If we're not accessing via a property wrapper, we don't need to adjust
850
- // the mutability.
851
- if (target == TargetImpl::Wrapper || target == TargetImpl::WrapperStorage) {
852
- auto var = cast<VarDecl>(accessor->getStorage ());
853
- if (auto mutability = var->getPropertyWrapperMutability ()) {
854
- // We consider the storage's mutability too because the wrapped property
855
- // might be part of a class, in case of which nothing is mutating.
856
- isGetterMutating = (mutability->Getter == PropertyWrapperMutability::Mutating)
857
- ? (storage->isGetterMutating () || storage->isSetterMutating ())
858
- : storage->isGetterMutating ();
859
- isSetterMutating = (mutability->Setter == PropertyWrapperMutability::Mutating)
860
- ? (storage->isGetterMutating () || storage->isSetterMutating ())
861
- : storage->isGetterMutating ();
862
- }
863
- }
864
-
865
- // If the accessor is mutating, then self should be referred as an l-value
866
- bool isSelfLValue = (isGetterMutating && isUsedForGetAccess) ||
867
- (isSetterMutating && isUsedForSetAccess);
868
-
869
- Expr *selfDRE = buildSelfReference (selfDecl, selfAccessKind, isSelfLValue,
866
+ Expr *selfDRE = buildSelfReference (selfDecl, selfAccessKind, isBaseLValue,
870
867
/* convertTy*/ selfTypeForAccess);
871
- if (isSelfLValue )
868
+ if (isBaseLValue )
872
869
selfTypeForAccess = LValueType::get (selfTypeForAccess);
873
870
874
871
if (!selfDRE->getType ()->isEqual (selfTypeForAccess)) {
@@ -1169,9 +1166,8 @@ synthesizeTrivialGetterBody(AccessorDecl *getter, TargetImpl target,
1169
1166
body.push_back (returnStmt);
1170
1167
}
1171
1168
1172
- // Don't mark local accessors as type-checked - captures still need to be computed.
1173
1169
return { BraceStmt::create (ctx, loc, body, loc, true ),
1174
- /* isTypeChecked=*/ !getter-> getDeclContext ()-> isLocalContext () };
1170
+ /* isTypeChecked=*/ true };
1175
1171
}
1176
1172
1177
1173
// / Synthesize the body of a getter which just directly accesses the
@@ -1446,9 +1442,8 @@ synthesizeTrivialSetterBodyWithStorage(AccessorDecl *setter,
1446
1442
1447
1443
createPropertyStoreOrCallSuperclassSetter (setter, valueDRE, storageToUse,
1448
1444
target, setterBody, ctx);
1449
- // Don't mark local accessors as type-checked - captures still need to be computed.
1450
1445
return { BraceStmt::create (ctx, loc, setterBody, loc, true ),
1451
- /* isTypeChecked=*/ !setter-> getDeclContext ()-> isLocalContext () };
1446
+ /* isTypeChecked=*/ true };
1452
1447
}
1453
1448
1454
1449
static std::pair<BraceStmt *, bool >
0 commit comments