mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Generalize storage implementations to support generalized accessors.
The storage kind has been replaced with three separate "impl kinds", one for each of the basic access kinds (read, write, and read/write). This makes it far easier to mix-and-match implementations of different accessors, as well as subtleties like implementing both a setter and an independent read/write operation. AccessStrategy has become a bit more explicit about how exactly the access should be implemented. For example, the accessor-based kinds now carry the exact accessor intended to be used. Also, I've shifted responsibilities slightly between AccessStrategy and AccessSemantics so that AccessSemantics::Ordinary can be used except in the sorts of semantic-bypasses that accessor synthesis wants. This requires knowing the correct DC of the access when computing the access strategy; the upshot is that SILGenFunction now needs a DC. Accessor synthesis has been reworked so that only the declarations are built immediately; body synthesis can be safely delayed out of the main decl-checking path. This caused a large number of ramifications, especially for lazy properties, and greatly inflated the size of this patch. That is... really regrettable. The impetus for changing this was necessity: I needed to rework accessor synthesis to end its reliance on distinctions like Stored vs. StoredWithTrivialAccessors, and those fixes were exposing serious re-entrancy problems, and fixing that... well. Breaking the fixes apart at this point would be a serious endeavor.
This commit is contained in:
@@ -481,32 +481,63 @@ static const Decl *getDeclForContext(const DeclContext *DC) {
|
||||
|
||||
namespace {
|
||||
struct Accessors {
|
||||
StorageKind Kind;
|
||||
uint8_t ReadImpl, WriteImpl, ReadWriteImpl;
|
||||
SmallVector<AccessorDecl *, 8> Decls;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
static StorageKind getRawStorageKind(AbstractStorageDecl::StorageKindTy kind) {
|
||||
static uint8_t getRawReadImplKind(swift::ReadImplKind kind) {
|
||||
switch (kind) {
|
||||
#define CASE(KIND) case AbstractStorageDecl::KIND: return StorageKind::KIND
|
||||
CASE(Stored);
|
||||
CASE(StoredWithTrivialAccessors);
|
||||
CASE(StoredWithObservers);
|
||||
CASE(InheritedWithObservers);
|
||||
CASE(Computed);
|
||||
CASE(ComputedWithMutableAddress);
|
||||
CASE(Addressed);
|
||||
CASE(AddressedWithTrivialAccessors);
|
||||
CASE(AddressedWithObservers);
|
||||
#define CASE(KIND) \
|
||||
case swift::ReadImplKind::KIND: \
|
||||
return uint8_t(serialization::ReadImplKind::KIND);
|
||||
CASE(Stored)
|
||||
CASE(Get)
|
||||
CASE(Inherited)
|
||||
CASE(Address)
|
||||
#undef CASE
|
||||
}
|
||||
llvm_unreachable("bad storage kind");
|
||||
llvm_unreachable("bad kind");
|
||||
}
|
||||
|
||||
static unsigned getRawWriteImplKind(swift::WriteImplKind kind) {
|
||||
switch (kind) {
|
||||
#define CASE(KIND) \
|
||||
case swift::WriteImplKind::KIND: \
|
||||
return uint8_t(serialization::WriteImplKind::KIND);
|
||||
CASE(Immutable)
|
||||
CASE(Stored)
|
||||
CASE(Set)
|
||||
CASE(StoredWithObservers)
|
||||
CASE(InheritedWithObservers)
|
||||
CASE(MutableAddress)
|
||||
#undef CASE
|
||||
}
|
||||
llvm_unreachable("bad kind");
|
||||
}
|
||||
|
||||
static unsigned getRawReadWriteImplKind(swift::ReadWriteImplKind kind) {
|
||||
switch (kind) {
|
||||
#define CASE(KIND) \
|
||||
case swift::ReadWriteImplKind::KIND: \
|
||||
return uint8_t(serialization::ReadWriteImplKind::KIND);
|
||||
CASE(Immutable)
|
||||
CASE(Stored)
|
||||
CASE(MaterializeForSet)
|
||||
CASE(MutableAddress)
|
||||
CASE(MaterializeToTemporary)
|
||||
#undef CASE
|
||||
}
|
||||
llvm_unreachable("bad kind");
|
||||
}
|
||||
|
||||
static Accessors getAccessors(const AbstractStorageDecl *storage) {
|
||||
Accessors accessors;
|
||||
accessors.Kind = getRawStorageKind(storage->getStorageKind());
|
||||
auto decls = storage->getAllAccessorFunctions();
|
||||
auto impl = storage->getImplInfo();
|
||||
accessors.ReadImpl = getRawReadImplKind(impl.getReadImpl());
|
||||
accessors.WriteImpl = getRawWriteImplKind(impl.getWriteImpl());
|
||||
accessors.ReadWriteImpl = getRawReadWriteImplKind(impl.getReadWriteImpl());
|
||||
auto decls = storage->getAllAccessors();
|
||||
accessors.Decls.append(decls.begin(), decls.end());
|
||||
return accessors;
|
||||
}
|
||||
@@ -3129,7 +3160,9 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
var->hasNonPatternBindingInit(),
|
||||
var->isGetterMutating(),
|
||||
var->isSetterMutating(),
|
||||
(unsigned) accessors.Kind,
|
||||
accessors.ReadImpl,
|
||||
accessors.WriteImpl,
|
||||
accessors.ReadWriteImpl,
|
||||
accessors.Decls.size(),
|
||||
addTypeRef(ty),
|
||||
addDeclRef(var->getOverriddenDecl()),
|
||||
@@ -3354,7 +3387,9 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
subscript->isObjC(),
|
||||
subscript->isGetterMutating(),
|
||||
subscript->isSetterMutating(),
|
||||
(unsigned) accessors.Kind,
|
||||
accessors.ReadImpl,
|
||||
accessors.WriteImpl,
|
||||
accessors.ReadWriteImpl,
|
||||
accessors.Decls.size(),
|
||||
addGenericEnvironmentRef(
|
||||
subscript->getGenericEnvironment()),
|
||||
|
||||
Reference in New Issue
Block a user