Skip to content

Commit 934d4d1

Browse files
committed
Requestify whether a decl is an ABI compatible override
This commit adds `IsABICompatibleOverrideRequest`, which checks if the decl is an override, and if so whether it's ABI compatible with the base This is then usedto replace the logic for computing `isValidKeyPathComponent` in addition to being used in `requiresNewVTableEntry`.
1 parent 9b7ab6b commit 934d4d1

File tree

5 files changed

+59
-58
lines changed

5 files changed

+59
-58
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -340,12 +340,7 @@ class alignas(1 << DeclAlignInBits) Decl {
340340
IsUserAccessible : 1
341341
);
342342

343-
SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1+1+1,
344-
/// Whether a keypath component can directly reference this storage,
345-
/// or if it must use the overridden declaration instead.
346-
HasComputedValidKeyPathComponent : 1,
347-
ValidKeyPathComponent : 1,
348-
343+
SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1,
349344
/// Whether this property is a type property (currently unfortunately
350345
/// called 'static').
351346
IsStatic : 1
@@ -4535,8 +4530,6 @@ class AbstractStorageDecl : public ValueDecl {
45354530
Bits.AbstractStorageDecl.IsStatic = IsStatic;
45364531
}
45374532

4538-
void computeIsValidKeyPathComponent();
4539-
45404533
OpaqueTypeDecl *OpaqueReturn = nullptr;
45414534

45424535
public:
@@ -4779,18 +4772,9 @@ class AbstractStorageDecl : public ValueDecl {
47794772
/// property from the given module?
47804773
bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;
47814774

4782-
void setIsValidKeyPathComponent(bool value) {
4783-
Bits.AbstractStorageDecl.HasComputedValidKeyPathComponent = true;
4784-
Bits.AbstractStorageDecl.ValidKeyPathComponent = value;
4785-
}
4786-
47874775
/// True if the storage can be referenced by a keypath directly.
47884776
/// Otherwise, its override must be referenced.
4789-
bool isValidKeyPathComponent() const {
4790-
if (!Bits.AbstractStorageDecl.HasComputedValidKeyPathComponent)
4791-
const_cast<AbstractStorageDecl *>(this)->computeIsValidKeyPathComponent();
4792-
return Bits.AbstractStorageDecl.ValidKeyPathComponent;
4793-
}
4777+
bool isValidKeyPathComponent() const;
47944778

47954779
/// True if the storage exports a property descriptor for key paths in
47964780
/// other modules.

include/swift/AST/TypeCheckRequests.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,23 @@ class EnumRawValuesRequest :
12551255
void cacheResult(bool value) const;
12561256
};
12571257

1258+
class IsABICompatibleOverrideRequest
1259+
: public SimpleRequest<IsABICompatibleOverrideRequest, bool(ValueDecl *),
1260+
CacheKind::Cached> {
1261+
public:
1262+
using SimpleRequest::SimpleRequest;
1263+
1264+
private:
1265+
friend SimpleRequest;
1266+
1267+
// Evaluation.
1268+
llvm::Expected<bool> evaluate(Evaluator &evaluator, ValueDecl *decl) const;
1269+
1270+
public:
1271+
// Caching.
1272+
bool isCached() const { return true; }
1273+
};
1274+
12581275
// Allow AnyValue to compare two Type values, even though Type doesn't
12591276
// support ==.
12601277
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,5 @@ SWIFT_REQUEST(TypeChecker, UnderlyingTypeRequest, Type(TypeAliasDecl *),
142142
SeparatelyCached, NoLocationInfo)
143143
SWIFT_REQUEST(TypeChecker, USRGenerationRequest, std::string(const ValueDecl *),
144144
Cached, NoLocationInfo)
145+
SWIFT_REQUEST(TypeChecker, IsABICompatibleOverrideRequest,
146+
bool(ValueDecl *), Cached, NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2142,32 +2142,15 @@ bool AbstractStorageDecl::isResilient(ModuleDecl *M,
21422142
llvm_unreachable("bad resilience expansion");
21432143
}
21442144

2145-
static bool isValidKeyPathComponent(AbstractStorageDecl *decl) {
2146-
// If this property or subscript is not an override, we can reference it
2147-
// from a keypath component.
2148-
auto base = decl->getOverriddenDecl();
2149-
if (!base)
2150-
return true;
2151-
2152-
// Otherwise, we can only reference it if the type is not ABI-compatible
2153-
// with the type of the base.
2154-
//
2155-
// If the type is ABI compatible with the type of the base, we have to
2156-
// reference the base instead.
2157-
auto baseInterfaceTy = base->getInterfaceType();
2158-
auto derivedInterfaceTy = decl->getInterfaceType();
2159-
2160-
auto selfInterfaceTy = decl->getDeclContext()->getDeclaredInterfaceType();
2161-
2162-
auto overrideInterfaceTy = selfInterfaceTy->adjustSuperclassMemberDeclType(
2163-
base, decl, baseInterfaceTy);
2164-
2165-
return !derivedInterfaceTy->matches(overrideInterfaceTy,
2166-
TypeMatchFlags::AllowABICompatible);
2167-
}
2168-
2169-
void AbstractStorageDecl::computeIsValidKeyPathComponent() {
2170-
setIsValidKeyPathComponent(::isValidKeyPathComponent(this));
2145+
bool AbstractStorageDecl::isValidKeyPathComponent() const {
2146+
// Check whether we're an ABI compatible override of another property. If we
2147+
// are, then the key path should refer to the base decl instead.
2148+
auto &ctx = getASTContext();
2149+
auto isABICompatibleOverride = evaluateOrDefault(
2150+
ctx.evaluator,
2151+
IsABICompatibleOverrideRequest{const_cast<AbstractStorageDecl *>(this)},
2152+
false);
2153+
return !isABICompatibleOverride;
21712154
}
21722155

21732156
bool AbstractStorageDecl::isGetterMutating() const {
@@ -6588,26 +6571,22 @@ static bool requiresNewVTableEntry(const AbstractFunctionDecl *decl) {
65886571
if (decl->isEffectiveLinkageMoreVisibleThan(base))
65896572
return true;
65906573

6591-
// If the method overrides something, we only need a new entry if the
6592-
// override has a more general AST type. However an abstraction
6593-
// change is OK; we don't want to add a whole new vtable entry just
6594-
// because an @in parameter because @owned, or whatever.
6595-
auto baseInterfaceTy = base->getInterfaceType();
6596-
auto derivedInterfaceTy = decl->getInterfaceType();
6597-
65986574
using Direction = ASTContext::OverrideGenericSignatureReqCheck;
65996575
if (!ctx.overrideGenericSignatureReqsSatisfied(
66006576
base, decl, Direction::BaseReqSatisfiedByDerived)) {
66016577
return true;
66026578
}
66036579

6604-
auto selfInterfaceTy = decl->getDeclContext()->getDeclaredInterfaceType();
6605-
6606-
auto overrideInterfaceTy = selfInterfaceTy->adjustSuperclassMemberDeclType(
6607-
base, decl, baseInterfaceTy);
6608-
6609-
return !derivedInterfaceTy->matches(overrideInterfaceTy,
6610-
TypeMatchFlags::AllowABICompatible);
6580+
// If this method is an ABI compatible override, then we don't need a new
6581+
// vtable entry. Otherwise, if it's not ABI compatible, for example if the
6582+
// base has a more general AST type, then we need a new entry. Note that an
6583+
// abstraction change is OK; we don't want to add a whole new vtable entry
6584+
// just because an @in parameter becomes @owned, or whatever.
6585+
auto isABICompatibleOverride = evaluateOrDefault(
6586+
ctx.evaluator,
6587+
IsABICompatibleOverrideRequest{const_cast<AbstractFunctionDecl *>(decl)},
6588+
false);
6589+
return !isABICompatibleOverride;
66116590
}
66126591

66136592
void AbstractFunctionDecl::computeNeedsNewVTableEntry() {

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1954,3 +1954,22 @@ OverriddenDeclsRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
19541954
return matcher.checkPotentialOverrides(matches,
19551955
OverrideCheckingAttempt::PerfectMatch);
19561956
}
1957+
1958+
llvm::Expected<bool>
1959+
IsABICompatibleOverrideRequest::evaluate(Evaluator &evaluator,
1960+
ValueDecl *decl) const {
1961+
auto base = decl->getOverriddenDecl();
1962+
if (!base)
1963+
return false;
1964+
1965+
auto baseInterfaceTy = base->getInterfaceType();
1966+
auto derivedInterfaceTy = decl->getInterfaceType();
1967+
1968+
auto selfInterfaceTy = decl->getDeclContext()->getDeclaredInterfaceType();
1969+
1970+
auto overrideInterfaceTy = selfInterfaceTy->adjustSuperclassMemberDeclType(
1971+
base, decl, baseInterfaceTy);
1972+
1973+
return derivedInterfaceTy->matches(overrideInterfaceTy,
1974+
TypeMatchFlags::AllowABICompatible);
1975+
}

0 commit comments

Comments
 (0)