Skip to content

Commit 60e1dfe

Browse files
committed
Sema: Use a request to compute AbstractStorageDecl::getImplInfo()
This just moves the code from the parser into a request. Sema will still overwrite the ImplInfo field for lazy properties and property wrappers; refactoring that is next.
1 parent bfe0ebb commit 60e1dfe

File tree

7 files changed

+211
-154
lines changed

7 files changed

+211
-154
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4385,6 +4385,7 @@ class AbstractStorageDecl : public ValueDecl {
43854385
friend class IsGetterMutatingRequest;
43864386
friend class IsSetterMutatingRequest;
43874387
friend class OpaqueReadOwnershipRequest;
4388+
friend class StorageImplInfoRequest;
43884389

43894390
public:
43904391
static const size_t MaxNumAccessors = 255;
@@ -4487,7 +4488,7 @@ class AbstractStorageDecl : public ValueDecl {
44874488
Type getValueInterfaceType() const;
44884489

44894490
/// Determine how this storage is implemented.
4490-
StorageImplInfo getImplInfo() const { return ImplInfo; }
4491+
StorageImplInfo getImplInfo() const;
44914492

44924493
/// Overwrite the registered implementation-info. This should be
44934494
/// used carefully.

include/swift/AST/TypeCheckRequests.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
namespace swift {
3131

32+
class AbstractStorageDecl;
3233
class GenericParamList;
3334
struct PropertyWrapperBackingPropertyInfo;
3435
class RequirementRepr;
@@ -810,6 +811,27 @@ class StoredPropertiesAndMissingMembersRequest :
810811
bool isCached() const { return true; }
811812
};
812813

814+
class StorageImplInfoRequest :
815+
public SimpleRequest<StorageImplInfoRequest,
816+
StorageImplInfo(AbstractStorageDecl *),
817+
CacheKind::SeparatelyCached> {
818+
public:
819+
using SimpleRequest::SimpleRequest;
820+
821+
private:
822+
friend SimpleRequest;
823+
824+
// Evaluation.
825+
llvm::Expected<StorageImplInfo>
826+
evaluate(Evaluator &evaluator, AbstractStorageDecl *decl) const;
827+
828+
public:
829+
// Separate caching.
830+
bool isCached() const { return true; }
831+
Optional<StorageImplInfo> getCachedResult() const;
832+
void cacheResult(StorageImplInfo value) const;
833+
};
834+
813835
// Allow AnyValue to compare two Type values, even though Type doesn't
814836
// support ==.
815837
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ SWIFT_TYPEID(LazyStoragePropertyRequest)
4545
SWIFT_TYPEID(TypeCheckFunctionBodyUntilRequest)
4646
SWIFT_TYPEID(StoredPropertiesRequest)
4747
SWIFT_TYPEID(StoredPropertiesAndMissingMembersRequest)
48+
SWIFT_TYPEID(StorageImplInfoRequest)

lib/AST/Decl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4659,6 +4659,14 @@ void ProtocolDecl::computeKnownProtocolKind() const {
46594659
const_cast<ProtocolDecl *>(this)->Bits.ProtocolDecl.KnownProtocol = value;
46604660
}
46614661

4662+
4663+
StorageImplInfo AbstractStorageDecl::getImplInfo() const {
4664+
ASTContext &ctx = getASTContext();
4665+
return evaluateOrDefault(ctx.evaluator,
4666+
StorageImplInfoRequest{const_cast<AbstractStorageDecl *>(this)},
4667+
StorageImplInfo::getSimpleStored(StorageIsMutable));
4668+
}
4669+
46624670
bool AbstractStorageDecl::hasPrivateAccessor() const {
46634671
for (auto accessor : getAllAccessors()) {
46644672
if (hasPrivateOrFilePrivateFormalAccess(accessor))

lib/AST/TypeCheckRequests.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,3 +634,20 @@ void OpaqueReadOwnershipRequest::cacheResult(OpaqueReadOwnership value) const {
634634
auto *storage = std::get<0>(getStorage());
635635
storage->setOpaqueReadOwnership(value);
636636
}
637+
638+
//----------------------------------------------------------------------------//
639+
// StorageImplInfoRequest computation.
640+
//----------------------------------------------------------------------------//
641+
642+
Optional<StorageImplInfo>
643+
StorageImplInfoRequest::getCachedResult() const {
644+
auto *storage = std::get<0>(getStorage());
645+
if (storage->LazySemanticInfo.ImplInfoComputed)
646+
return storage->ImplInfo;
647+
return None;
648+
}
649+
650+
void StorageImplInfoRequest::cacheResult(StorageImplInfo value) const {
651+
auto *storage = std::get<0>(getStorage());
652+
storage->setImplInfo(value);
653+
}

lib/Parse/ParseDecl.cpp

Lines changed: 6 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -4470,12 +4470,9 @@ struct Parser::ParsedAccessors {
44704470
#include "swift/AST/AccessorKinds.def"
44714471

44724472
void record(Parser &P, AbstractStorageDecl *storage, bool invalid,
4473-
const DeclAttributes &attrs,
44744473
SmallVectorImpl<Decl *> &decls);
44754474

4476-
StorageImplInfo
4477-
classify(Parser &P, AbstractStorageDecl *storage, bool invalid,
4478-
const DeclAttributes &attrs);
4475+
void classify(Parser &P, AbstractStorageDecl *storage, bool invalid);
44794476

44804477
/// Add an accessor. If there's an existing accessor of this kind,
44814478
/// return it. The new accessor is still remembered but will be
@@ -4908,7 +4905,7 @@ Parser::parseDeclVarGetSet(Pattern *pattern, ParseDeclOptions Flags,
49084905
accessors.Set->setInvalid();
49094906
}
49104907

4911-
accessors.record(*this, PrimaryVar, Invalid, Attributes, Decls);
4908+
accessors.record(*this, PrimaryVar, Invalid, Decls);
49124909

49134910
return makeParserResult(PrimaryVar);
49144911
}
@@ -4936,10 +4933,8 @@ AccessorDecl *Parser::ParsedAccessors::add(AccessorDecl *accessor) {
49364933
/// Record a bunch of parsed accessors into the given abstract storage decl.
49374934
void Parser::ParsedAccessors::record(Parser &P, AbstractStorageDecl *storage,
49384935
bool invalid,
4939-
const DeclAttributes &attrs,
49404936
SmallVectorImpl<Decl *> &decls) {
4941-
auto storageKind = classify(P, storage, invalid, attrs);
4942-
storage->setImplInfo(storageKind);
4937+
classify(P, storage, invalid);
49434938

49444939
decls.append(Accessors.begin(), Accessors.end());
49454940
storage->setAccessors(LBLoc, Accessors, RBLoc);
@@ -4979,53 +4974,8 @@ static void diagnoseAndIgnoreObservers(Parser &P,
49794974
}
49804975
}
49814976

4982-
/// Gets the storage info of the provided storage decl if it has the
4983-
/// @_hasStorage attribute and it's not in SIL mode.
4984-
///
4985-
/// In this case, we say the decl is:
4986-
///
4987-
/// Read:
4988-
/// - Stored, always
4989-
/// Write:
4990-
/// - Stored, if the decl is a 'var'.
4991-
/// - StoredWithObservers, if the decl has a setter
4992-
/// - This indicates that the original decl had a 'didSet' and/or 'willSet'
4993-
/// - InheritedWithObservers, if the decl has a setter and is an overridde.
4994-
/// - Immutable, if the decl is a 'let' or it does not have a setter.
4995-
/// ReadWrite:
4996-
/// - Stored, if the decl has no accessors listed.
4997-
/// - Immutable, if the decl is a 'let' or it does not have a setter.
4998-
/// - MaterializeToTemporary, if the decl has a setter.
4999-
static StorageImplInfo classifyWithHasStorageAttr(
5000-
Parser::ParsedAccessors &accessors, ASTContext &ctx,
5001-
VarDecl *var, const DeclAttributes &attrs) {
5002-
5003-
WriteImplKind writeImpl;
5004-
ReadWriteImplKind readWriteImpl;
5005-
5006-
if (accessors.Get && accessors.Set) {
5007-
// If we see `@_hasStorage var x: T { get set }`, then our property has
5008-
// willSet/didSet observers.
5009-
writeImpl = attrs.hasAttribute<OverrideAttr>() ?
5010-
WriteImplKind::InheritedWithObservers :
5011-
WriteImplKind::StoredWithObservers;
5012-
readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
5013-
} else if (var->isLet()) {
5014-
writeImpl = WriteImplKind::Immutable;
5015-
readWriteImpl = ReadWriteImplKind::Immutable;
5016-
} else {
5017-
// Default to stored writes.
5018-
writeImpl = WriteImplKind::Stored;
5019-
readWriteImpl = ReadWriteImplKind::Stored;
5020-
}
5021-
5022-
// Always force Stored reads if @_hasStorage is present.
5023-
return StorageImplInfo(ReadImplKind::Stored, writeImpl, readWriteImpl);
5024-
}
5025-
5026-
StorageImplInfo
5027-
Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
5028-
bool invalid, const DeclAttributes &attrs) {
4977+
void Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
4978+
bool invalid) {
50294979
// If there was a problem parsing accessors, mark all parsed accessors
50304980
// as invalid to avoid tripping up later invariants.
50314981
// We also want to avoid diagnose missing accessors if something
@@ -5092,102 +5042,6 @@ Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
50925042
} else if (Modify) {
50935043
diagnoseConflictingAccessors(P, Modify, MutableAddress);
50945044
}
5095-
5096-
if (auto *var = dyn_cast<VarDecl>(storage)) {
5097-
// Allow the @_hasStorage attribute to override all the accessors we parsed
5098-
// when making the final classification.
5099-
if (attrs.hasAttribute<HasStorageAttr>()) {
5100-
// The SIL rules for @_hasStorage are slightly different from the non-SIL
5101-
// rules. In SIL mode, @_hasStorage marks that the type is simply stored,
5102-
// and the only thing that determines mutability is the existence of the
5103-
// setter.
5104-
//
5105-
// FIXME: SIL should not be special cased here. The behavior should be
5106-
// consistent between SIL and non-SIL.
5107-
// The strategy here should be to keep track of all opaque accessors
5108-
// along with enough information to access the storage trivially
5109-
// if allowed. This could be a representational change to
5110-
// StorageImplInfo such that it keeps a bitset of listed accessors
5111-
// and dynamically determines the access strategy from that.
5112-
if (P.isInSILMode())
5113-
return StorageImplInfo::getSimpleStored(
5114-
StorageIsMutable_t(Set != nullptr));
5115-
5116-
return classifyWithHasStorageAttr(*this, P.Context, var, attrs);
5117-
}
5118-
}
5119-
5120-
// 'get', 'read', and a non-mutable addressor are all exclusive.
5121-
ReadImplKind readImpl;
5122-
if (Get) {
5123-
readImpl = ReadImplKind::Get;
5124-
} else if (Read) {
5125-
readImpl = ReadImplKind::Read;
5126-
} else if (Address) {
5127-
readImpl = ReadImplKind::Address;
5128-
5129-
// If there's a writing accessor of any sort, there must also be a
5130-
// reading accessor.
5131-
} else if (auto mutator = findFirstMutator()) {
5132-
readImpl = ReadImplKind::Get;
5133-
5134-
// Subscripts always have to have some sort of accessor; they can't be
5135-
// purely stored.
5136-
} else if (isa<SubscriptDecl>(storage)) {
5137-
readImpl = ReadImplKind::Get;
5138-
5139-
// Check if we have observers.
5140-
} else if (WillSet || DidSet) {
5141-
if (attrs.hasAttribute<OverrideAttr>()) {
5142-
readImpl = ReadImplKind::Inherited;
5143-
} else {
5144-
readImpl = ReadImplKind::Stored;
5145-
}
5146-
5147-
// Otherwise, it's stored.
5148-
} else {
5149-
readImpl = ReadImplKind::Stored;
5150-
}
5151-
5152-
// Prefer using 'set' and 'modify' over a mutable addressor.
5153-
WriteImplKind writeImpl;
5154-
ReadWriteImplKind readWriteImpl;
5155-
if (Set) {
5156-
writeImpl = WriteImplKind::Set;
5157-
if (Modify) {
5158-
readWriteImpl = ReadWriteImplKind::Modify;
5159-
} else {
5160-
readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
5161-
}
5162-
} else if (Modify) {
5163-
writeImpl = WriteImplKind::Modify;
5164-
readWriteImpl = ReadWriteImplKind::Modify;
5165-
} else if (MutableAddress) {
5166-
writeImpl = WriteImplKind::MutableAddress;
5167-
readWriteImpl = ReadWriteImplKind::MutableAddress;
5168-
5169-
// Check if we have observers.
5170-
} else if (readImpl == ReadImplKind::Inherited) {
5171-
writeImpl = WriteImplKind::InheritedWithObservers;
5172-
readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
5173-
5174-
// Otherwise, it's stored.
5175-
} else if (readImpl == ReadImplKind::Stored) {
5176-
if (WillSet || DidSet) {
5177-
writeImpl = WriteImplKind::StoredWithObservers;
5178-
readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
5179-
} else {
5180-
writeImpl = WriteImplKind::Stored;
5181-
readWriteImpl = ReadWriteImplKind::Stored;
5182-
}
5183-
5184-
// Otherwise, it's immutable.
5185-
} else {
5186-
writeImpl = WriteImplKind::Immutable;
5187-
readWriteImpl = ReadWriteImplKind::Immutable;
5188-
}
5189-
5190-
return StorageImplInfo(readImpl, writeImpl, readWriteImpl);
51915045
}
51925046

51935047

@@ -6598,8 +6452,7 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
65986452
Invalid = true;
65996453
}
66006454

6601-
accessors.record(*this, Subscript, (Invalid || !Status.isSuccess()),
6602-
Attributes, Decls);
6455+
accessors.record(*this, Subscript, (Invalid || !Status.isSuccess()), Decls);
66036456

66046457
// No need to setLocalDiscriminator because subscripts cannot
66056458
// validly appear outside of type decls.

0 commit comments

Comments
 (0)