Skip to content

Commit 8785454

Browse files
committed
[Property Wrappers] Simplify PropertyWrapperLValuenessRequest::evaluate
by computing the lvalue sequence in reverse order.
1 parent 37e4542 commit 8785454

File tree

2 files changed

+53
-83
lines changed

2 files changed

+53
-83
lines changed

include/swift/AST/PropertyWrappers.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ struct PropertyWrapperLValueness {
133133
llvm::SmallVector<bool, 1> isLValueForGetAccess;
134134
llvm::SmallVector<bool, 1> isLValueForSetAccess;
135135

136+
PropertyWrapperLValueness(unsigned numWrappers)
137+
: isLValueForGetAccess(numWrappers), isLValueForSetAccess(numWrappers) {}
138+
136139
bool operator==(PropertyWrapperLValueness other) const {
137140
return (isLValueForGetAccess == other.isLValueForGetAccess &&
138141
isLValueForSetAccess == other.isLValueForSetAccess);

lib/Sema/TypeCheckStorage.cpp

Lines changed: 50 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2500,100 +2500,67 @@ PropertyWrapperMutabilityRequest::evaluate(Evaluator &,
25002500
Optional<PropertyWrapperLValueness>
25012501
PropertyWrapperLValuenessRequest::evaluate(Evaluator &,
25022502
VarDecl *var) const {
2503-
VarDecl *VD = var;
2504-
unsigned numWrappers = var->getAttachedPropertyWrappers().size();
2505-
bool isProjectedValue = false;
2506-
if (numWrappers < 1) {
2507-
VD = var->getOriginalWrappedProperty(
2503+
VarDecl *VD = var;
2504+
unsigned numWrappers = var->getAttachedPropertyWrappers().size();
2505+
bool isProjectedValue = false;
2506+
if (numWrappers < 1) {
2507+
VD = var->getOriginalWrappedProperty(
25082508
PropertyWrapperSynthesizedPropertyKind::StorageWrapper);
2509-
numWrappers = 1; // Can't compose projected values
2510-
isProjectedValue = true;
2511-
}
2509+
numWrappers = 1; // Can't compose projected values
2510+
isProjectedValue = true;
2511+
}
25122512

2513-
if (!VD)
2514-
return None;
2513+
if (!VD)
2514+
return None;
25152515

2516-
auto varMember = isProjectedValue
2516+
auto varMember = isProjectedValue
25172517
? &PropertyWrapperTypeInfo::projectedValueVar
25182518
: &PropertyWrapperTypeInfo::valueVar;
25192519

2520-
// Calling the getter (or setter) on the nth property wrapper in the chain
2521-
// is done as follows:
2522-
// 1. call the getter on the (n-1)th property wrapper instance to get the
2523-
// nth property wrapper instance
2524-
// 2. call the getter (or setter) on the nth property wrapper instance
2525-
// 3. if (2) is a mutating access, call the setter on the (n-1)th property
2526-
// wrapper instance to write back the mutated value
2527-
2528-
// Below, we determine which of these property wrapper instances need to be
2529-
// accessed mutating-ly, and therefore should be l-values.
2530-
2531-
// The variables used are:
2532-
//
2533-
// - prevWrappersMutabilityForGet:
2534-
//
2535-
// The mutability needed for the first (n-1) wrapper instances to be
2536-
// able to call the getter on the (n-1)th instance, for step (1) above
2537-
//
2538-
// - prevWrappersMutabilityForGetAndSet:
2539-
//
2540-
// The mutability needed for the first (n-1) wrapper instances to be
2541-
// able to call both the getter and setter on the (n-1)th instance, for
2542-
// steps (1) and (3) above
2543-
//
2544-
// - mutability:
2545-
//
2546-
// The mutability needed for calling the getter / setter on the
2547-
// nth wrapper instance, for step (2) above.
2548-
2549-
llvm::SmallVector<PropertyWrapperMutability::Value, 1>
2550-
prevWrappersMutabilityForGet, prevWrappersMutabilityForGetAndSet;
2520+
auto accessorMutability = [&](unsigned wrapperIndex) -> PropertyWrapperMutability {
25512521
PropertyWrapperMutability mutability;
2522+
auto wrapperInfo = VD->getAttachedPropertyWrapperTypeInfo(wrapperIndex);
2523+
mutability.Getter = getGetterMutatingness(wrapperInfo.*varMember);
2524+
mutability.Setter = getSetterMutatingness(wrapperInfo.*varMember,
2525+
var->getInnermostDeclContext());
2526+
return mutability;
2527+
};
25522528

2553-
auto firstWrapperInfo = VD->getAttachedPropertyWrapperTypeInfo(0);
2554-
mutability.Getter = getGetterMutatingness(firstWrapperInfo.*varMember);
2555-
mutability.Setter = getSetterMutatingness(firstWrapperInfo.*varMember,
2556-
var->getInnermostDeclContext());
2529+
// Calling the getter (or setter) on the nth property wrapper in the chain
2530+
// is done as follows:
2531+
// 1. call the getter on the (n-1)th property wrapper instance to get the
2532+
// nth property wrapper instance
2533+
// 2. call the getter (or setter) on the nth property wrapper instance
2534+
// 3. if (2) is a mutating access, call the setter on the (n-1)th property
2535+
// wrapper instance to write back the mutated value
25572536

2558-
for (unsigned i : range(1, numWrappers)) {
2559-
if (mutability.Getter == PropertyWrapperMutability::Mutating) {
2560-
prevWrappersMutabilityForGet = prevWrappersMutabilityForGetAndSet;
2561-
}
2562-
if (mutability.Getter != PropertyWrapperMutability::Mutating &&
2563-
mutability.Setter != PropertyWrapperMutability::Mutating) {
2564-
prevWrappersMutabilityForGetAndSet = prevWrappersMutabilityForGet;
2565-
}
2566-
prevWrappersMutabilityForGet.push_back(mutability.Getter);
2567-
prevWrappersMutabilityForGetAndSet.push_back(
2568-
std::max(mutability.Getter, mutability.Setter));
2569-
auto wrapperInfo = VD->getAttachedPropertyWrapperTypeInfo(i);
2570-
mutability.Getter = getGetterMutatingness(wrapperInfo.*varMember);
2571-
mutability.Setter = getSetterMutatingness(wrapperInfo.*varMember,
2572-
var->getInnermostDeclContext());
2573-
}
2537+
// Below, we determine which of these property wrapper instances need to be
2538+
// accessed mutating-ly, and therefore should be l-values.
25742539

2575-
auto mutabilitySequenceForLastGet =
2576-
(mutability.Getter == PropertyWrapperMutability::Mutating)
2577-
? &prevWrappersMutabilityForGetAndSet
2578-
: &prevWrappersMutabilityForGet;
2579-
auto mutabilitySequenceForLastSet =
2580-
(mutability.Setter == PropertyWrapperMutability::Mutating)
2581-
? &prevWrappersMutabilityForGetAndSet
2582-
: &prevWrappersMutabilityForGet;
2583-
2584-
PropertyWrapperLValueness lvalueness;
2585-
for (unsigned i : range(numWrappers - 1)) {
2586-
lvalueness.isLValueForGetAccess.push_back(
2587-
(*mutabilitySequenceForLastGet)[i] == PropertyWrapperMutability::Mutating);
2588-
lvalueness.isLValueForSetAccess.push_back(
2589-
(*mutabilitySequenceForLastSet)[i] == PropertyWrapperMutability::Mutating);
2590-
}
2591-
lvalueness.isLValueForGetAccess.push_back(
2592-
mutability.Getter == PropertyWrapperMutability::Mutating);
2593-
lvalueness.isLValueForSetAccess.push_back(
2594-
mutability.Setter == PropertyWrapperMutability::Mutating);
2540+
unsigned innermostWrapperIdx = numWrappers - 1;
2541+
auto lastAccess = accessorMutability(innermostWrapperIdx);
2542+
2543+
PropertyWrapperLValueness lvalueness(numWrappers);
2544+
lvalueness.isLValueForGetAccess[innermostWrapperIdx] =
2545+
lastAccess.Getter == PropertyWrapperMutability::Mutating;
2546+
lvalueness.isLValueForSetAccess[innermostWrapperIdx] =
2547+
lastAccess.Setter == PropertyWrapperMutability::Mutating;
2548+
2549+
auto lastAccessForGet = lastAccess.Getter;
2550+
auto lastAccessForSet = lastAccess.Setter;
2551+
for (int i = innermostWrapperIdx - 1; i >= 0; --i) {
2552+
auto access = accessorMutability(i);
2553+
2554+
lastAccessForGet = access.composeWith(lastAccessForGet);
2555+
lastAccessForSet = access.composeWith(lastAccessForSet);
2556+
2557+
lvalueness.isLValueForGetAccess[i] =
2558+
lastAccessForGet == PropertyWrapperMutability::Mutating;
2559+
lvalueness.isLValueForSetAccess[i] =
2560+
lastAccessForSet == PropertyWrapperMutability::Mutating;
2561+
}
25952562

2596-
return lvalueness;
2563+
return lvalueness;
25972564
}
25982565

25992566
PropertyWrapperBackingPropertyInfo

0 commit comments

Comments
 (0)