Skip to content

Commit 61261fc

Browse files
authored
Merge pull request #26326 from jckarter/property-wrapper-composition-mutatiness
Sema: Correct composition of property wrappers.
2 parents d6053dc + fa4dd15 commit 61261fc

16 files changed

+607
-76
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ SWIFT_TYPEID_NAMED(Decl *, Decl)
2222
SWIFT_TYPEID(Type)
2323
SWIFT_TYPEID(PropertyWrapperBackingPropertyInfo)
2424
SWIFT_TYPEID(PropertyWrapperTypeInfo)
25+
SWIFT_TYPEID_NAMED(Optional<PropertyWrapperMutability>, PropertyWrapperMutability)
2526
SWIFT_TYPEID_NAMED(CustomAttr *, CustomAttr)
2627
SWIFT_TYPEID_NAMED(TypeAliasDecl *, TypeAliasDecl)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class CustomAttr;
2424
class NominalTypeDecl;
2525
struct PropertyWrapperBackingPropertyInfo;
2626
struct PropertyWrapperTypeInfo;
27+
struct PropertyWrapperMutability;
2728
class Type;
2829
class VarDecl;
2930
class TypeAliasDecl;

include/swift/AST/Decl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ namespace swift {
7979
struct PrintOptions;
8080
struct PropertyWrapperBackingPropertyInfo;
8181
struct PropertyWrapperTypeInfo;
82+
struct PropertyWrapperMutability;
8283
class ProtocolDecl;
8384
class ProtocolType;
8485
struct RawComment;
@@ -5065,6 +5066,11 @@ class VarDecl : public AbstractStorageDecl {
50655066
PropertyWrapperBackingPropertyInfo
50665067
getPropertyWrapperBackingPropertyInfo() const;
50675068

5069+
/// Retrieve information about the mutability of the composed
5070+
/// property wrappers.
5071+
Optional<PropertyWrapperMutability>
5072+
getPropertyWrapperMutability() const;
5073+
50685074
/// Retrieve the backing storage property for a property that has an
50695075
/// attached property wrapper.
50705076
///

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4481,8 +4481,9 @@ ERROR(property_wrapper_attribute_not_on_property, none,
44814481
NOTE(property_wrapper_declared_here,none,
44824482
"property wrapper type %0 declared here", (DeclName))
44834483

4484-
ERROR(property_wrapper_composition_not_implemented, none,
4485-
"multiple property wrappers are not supported", ())
4484+
ERROR(property_wrapper_mutating_get_composed_to_get_only,none,
4485+
"property wrapper %0 with a mutating getter cannot be composed inside "
4486+
"get-only property wrapper %1", (Type, Type))
44864487

44874488
ERROR(property_wrapper_local,none,
44884489
"property wrappers are not yet supported on local properties", ())

include/swift/AST/PropertyWrappers.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,47 @@ struct PropertyWrapperTypeInfo {
7777
}
7878
};
7979

80+
/// Describes the mutability of the operations on a property wrapper or composition.
81+
struct PropertyWrapperMutability {
82+
enum Value: uint8_t {
83+
Nonmutating = 0,
84+
Mutating = 1,
85+
DoesntExist = 2,
86+
};
87+
88+
Value Getter, Setter;
89+
90+
/// Get the mutability of a composed access chained after accessing a wrapper with `this`
91+
/// getter and setter mutability.
92+
Value composeWith(Value x) {
93+
switch (x) {
94+
case DoesntExist:
95+
return DoesntExist;
96+
97+
// If an operation is nonmutating, then its input relies only on the
98+
// mutating-ness of the outer wrapper's get operation.
99+
case Nonmutating:
100+
return Getter;
101+
102+
// If it's mutating, then it relies
103+
// on a) the outer wrapper having a setter to exist at all, and b) the
104+
// mutating-ness of either the getter or setter, since we need both to
105+
// perform a writeback cycle.
106+
case Mutating:
107+
if (Setter == DoesntExist) {
108+
return DoesntExist;
109+
}
110+
return std::max(Getter, Setter);
111+
}
112+
}
113+
114+
bool operator==(PropertyWrapperMutability other) const {
115+
return Getter == other.Getter && Setter == other.Setter;
116+
}
117+
};
118+
119+
void simple_display(llvm::raw_ostream &os, PropertyWrapperMutability m);
120+
80121
/// Describes the backing property of a property that has an attached wrapper.
81122
struct PropertyWrapperBackingPropertyInfo {
82123
/// The backing property.

include/swift/AST/TypeCheckRequests.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace swift {
3232
class AbstractStorageDecl;
3333
class GenericParamList;
3434
struct PropertyWrapperBackingPropertyInfo;
35+
struct PropertyWrapperMutability;
3536
class RequirementRepr;
3637
class SpecializeAttr;
3738
class TypeAliasDecl;
@@ -579,6 +580,26 @@ class PropertyWrapperBackingPropertyTypeRequest :
579580
bool isCached() const;
580581
};
581582

583+
/// Request information about the mutability of composed property wrappers.
584+
class PropertyWrapperMutabilityRequest :
585+
public SimpleRequest<PropertyWrapperMutabilityRequest,
586+
Optional<PropertyWrapperMutability> (VarDecl *),
587+
CacheKind::Cached> {
588+
public:
589+
using SimpleRequest::SimpleRequest;
590+
591+
private:
592+
friend SimpleRequest;
593+
594+
// Evaluation.
595+
llvm::Expected<Optional<PropertyWrapperMutability>>
596+
evaluate(Evaluator &evaluator, VarDecl *var) const;
597+
598+
public:
599+
// Caching
600+
bool isCached() const;
601+
};
602+
582603
/// Request information about the backing property for properties that have
583604
/// attached property wrappers.
584605
class PropertyWrapperBackingPropertyInfoRequest :

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ SWIFT_TYPEID(StructuralTypeRequest)
3232
SWIFT_TYPEID(DefaultTypeRequest)
3333
SWIFT_TYPEID(MangleLocalTypeDeclRequest)
3434
SWIFT_TYPEID(PropertyWrapperTypeInfoRequest)
35+
SWIFT_TYPEID(PropertyWrapperMutabilityRequest)
3536
SWIFT_TYPEID(AttachedPropertyWrappersRequest)
3637
SWIFT_TYPEID(AttachedPropertyWrapperTypeRequest)
3738
SWIFT_TYPEID(PropertyWrapperBackingPropertyTypeRequest)
@@ -46,4 +47,4 @@ SWIFT_TYPEID(LazyStoragePropertyRequest)
4647
SWIFT_TYPEID(TypeCheckFunctionBodyUntilRequest)
4748
SWIFT_TYPEID(StoredPropertiesRequest)
4849
SWIFT_TYPEID(StoredPropertiesAndMissingMembersRequest)
49-
SWIFT_TYPEID(StorageImplInfoRequest)
50+
SWIFT_TYPEID(StorageImplInfoRequest)

include/swift/Basic/AnyValue.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@ namespace llvm {
165165
bool operator!=(const TinyPtrVector<T> &lhs, const TinyPtrVector<T> &rhs) {
166166
return !(lhs == rhs);
167167
}
168+
169+
template<typename T>
170+
void simple_display(raw_ostream &out, const Optional<T> &opt) {
171+
if (opt) {
172+
simple_display(out, *opt);
173+
}
174+
out << "None";
175+
}
168176
} // end namespace llvm
169177

170178
#endif //

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3611,10 +3611,11 @@ OpaqueTypeArchetypeType::get(OpaqueTypeDecl *Decl,
36113611
}
36123612
}
36133613
#else
3614-
// Assert that there are no same type constraints on the underlying type.
3614+
// Assert that there are no same type constraints on the underlying type
36153615
// or its associated types.
36163616
//
3617-
// This should not be possible until we add where clause support.
3617+
// This should not be possible until we add where clause support, with the
3618+
// exception of generic base class constraints (handled below).
36183619
# ifndef NDEBUG
36193620
for (auto reqt :
36203621
Decl->getOpaqueInterfaceGenericSignature()->getRequirements()) {

lib/AST/Decl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5488,6 +5488,16 @@ VarDecl::getPropertyWrapperBackingPropertyInfo() const {
54885488
PropertyWrapperBackingPropertyInfo());
54895489
}
54905490

5491+
Optional<PropertyWrapperMutability>
5492+
VarDecl::getPropertyWrapperMutability() const {
5493+
auto &ctx = getASTContext();
5494+
auto mutableThis = const_cast<VarDecl *>(this);
5495+
return evaluateOrDefault(
5496+
ctx.evaluator,
5497+
PropertyWrapperMutabilityRequest{mutableThis},
5498+
None);
5499+
}
5500+
54915501
VarDecl *VarDecl::getPropertyWrapperBackingProperty() const {
54925502
return getPropertyWrapperBackingPropertyInfo().backingVar;
54935503
}

0 commit comments

Comments
 (0)