Skip to content

Commit f796e27

Browse files
[TypeChecker] Requestify DynamicCallableAttribute check
1 parent c1e517a commit f796e27

File tree

6 files changed

+64
-12
lines changed

6 files changed

+64
-12
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,29 @@ class HasDynamicMemberLookupAttributeRequest
19991999
}
20002000
};
20012001

2002+
/// Computes whether the specified type or a super-class/super-protocol has the
2003+
/// @dynamicCallable attribute on it.
2004+
class HasDynamicCallableAttributeRequest
2005+
: public SimpleRequest<HasDynamicCallableAttributeRequest,
2006+
bool(CanType), CacheKind::Cached> {
2007+
public:
2008+
using SimpleRequest::SimpleRequest;
2009+
2010+
private:
2011+
friend SimpleRequest;
2012+
2013+
// Evaluation.
2014+
llvm::Expected<bool> evaluate(Evaluator &evaluator, CanType ty) const;
2015+
2016+
public:
2017+
bool isCached() const {
2018+
// Don't cache types containing type variables, as they must not outlive
2019+
// the constraint system that created them.
2020+
auto ty = std::get<0>(getStorage());
2021+
return !ty->hasTypeVariable();
2022+
}
2023+
};
2024+
20022025
/// Determines the type of a given pattern.
20032026
///
20042027
/// Note that this returns the "raw" pattern type, which can involve

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ SWIFT_REQUEST(TypeChecker, HasCircularRawValueRequest,
8181
bool(EnumDecl *), Cached, NoLocationInfo)
8282
SWIFT_REQUEST(TypeChecker, HasDynamicMemberLookupAttributeRequest,
8383
bool(CanType), Cached, NoLocationInfo)
84+
SWIFT_REQUEST(TypeChecker, HasDynamicCallableAttributeRequest,
85+
bool(CanType), Cached, NoLocationInfo)
8486
SWIFT_REQUEST(TypeChecker, InferredGenericSignatureRequest,
8587
GenericSignature (ModuleDecl *, GenericSignatureImpl *,
8688
GenericParamList *,

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,10 @@ class alignas(1 << TypeAlignInBits) TypeBase {
836836
/// Return true if the specified type or a super-class/super-protocol has the
837837
/// @dynamicMemberLookup attribute on it.
838838
bool hasDynamicMemberLookupAttribute();
839+
840+
/// Return true if the specified type or a super-class/super-protocol has the
841+
/// @dynamicCallable attribute on it.
842+
bool hasDynamicCallableAttribute();
839843

840844
/// Retrieve the superclass of this type.
841845
///

lib/AST/Type.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,13 @@ bool TypeBase::hasDynamicMemberLookupAttribute() {
14991499
ctx.evaluator, HasDynamicMemberLookupAttributeRequest{canTy}, false);
15001500
}
15011501

1502+
bool TypeBase::hasDynamicCallableAttribute() {
1503+
auto canTy = getCanonicalType();
1504+
auto &ctx = canTy->getASTContext();
1505+
return evaluateOrDefault(
1506+
ctx.evaluator, HasDynamicCallableAttributeRequest{canTy}, false);
1507+
}
1508+
15021509
Type TypeBase::getSuperclass(bool useArchetypes) {
15031510
auto *nominalDecl = getAnyNominal();
15041511
auto *classDecl = dyn_cast_or_null<ClassDecl>(nominalDecl);

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,7 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator(
515515
}
516516

517517
// Handling an apply for a nominal type that supports @dynamicCallable.
518-
auto nominal = fnTy->getAnyNominal();
519-
if (nominal && nominal->getAttrs().hasAttribute<DynamicCallableAttr>()) {
518+
if (fnTy->hasDynamicCallableAttribute()) {
520519
return getConstraintLocator(anchor, LocatorPathElt::ApplyFunction());
521520
}
522521

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4233,18 +4233,18 @@ IsCallableNominalTypeRequest::evaluate(Evaluator &evaluator, CanType ty,
42334233
});
42344234
}
42354235

4236-
llvm::Expected<bool>
4237-
HasDynamicMemberLookupAttributeRequest::evaluate(Evaluator &evaluator,
4238-
CanType ty) const {
4236+
template <class DynamicAttribute>
4237+
static bool checkForDynamicAttribute(CanType ty,
4238+
llvm::function_ref<bool (Type)> hasAttribute) {
42394239
// If this is an archetype type, check if any types it conforms to
42404240
// (superclass or protocols) have the attribute.
42414241
if (auto archetype = dyn_cast<ArchetypeType>(ty)) {
42424242
for (auto proto : archetype->getConformsTo()) {
4243-
if (proto->getDeclaredType()->hasDynamicMemberLookupAttribute())
4243+
if (hasAttribute(proto->getDeclaredType()))
42444244
return true;
42454245
}
42464246
if (auto superclass = archetype->getSuperclass()) {
4247-
if (superclass->hasDynamicMemberLookupAttribute())
4247+
if (hasAttribute(superclass))
42484248
return true;
42494249
}
42504250
}
@@ -4253,33 +4253,50 @@ HasDynamicMemberLookupAttributeRequest::evaluate(Evaluator &evaluator,
42534253
// attribute.
42544254
if (auto protocolComp = dyn_cast<ProtocolCompositionType>(ty)) {
42554255
for (auto member : protocolComp->getMembers()) {
4256-
if (member->hasDynamicMemberLookupAttribute())
4256+
if (hasAttribute(member))
42574257
return true;
42584258
}
42594259
}
42604260

42614261
// Otherwise, this must be a nominal type.
4262-
// Dynamic member lookup doesn't work for tuples, etc.
4262+
// Neither Dynamic member lookup or Dynamic Callable doesn't
4263+
// work for tuples, etc.
42634264
auto nominal = ty->getAnyNominal();
42644265
if (!nominal)
42654266
return false;
42664267

42674268
// If this type has the attribute on it, then yes!
4268-
if (nominal->getAttrs().hasAttribute<DynamicMemberLookupAttr>())
4269+
if (nominal->getAttrs().hasAttribute<DynamicAttribute>())
42694270
return true;
42704271

42714272
// Check the protocols the type conforms to.
42724273
for (auto proto : nominal->getAllProtocols()) {
4273-
if (proto->getDeclaredType()->hasDynamicMemberLookupAttribute())
4274+
if (hasAttribute(proto->getDeclaredType()))
42744275
return true;
42754276
}
42764277

42774278
// Check the superclass if present.
42784279
if (auto classDecl = dyn_cast<ClassDecl>(nominal)) {
42794280
if (auto superclass = classDecl->getSuperclass()) {
4280-
if (superclass->hasDynamicMemberLookupAttribute())
4281+
if (hasAttribute(superclass))
42814282
return true;
42824283
}
42834284
}
42844285
return false;
42854286
}
4287+
4288+
llvm::Expected<bool>
4289+
HasDynamicMemberLookupAttributeRequest::evaluate(Evaluator &evaluator,
4290+
CanType ty) const {
4291+
return checkForDynamicAttribute<DynamicMemberLookupAttr>(ty, [](Type type) {
4292+
return type->hasDynamicMemberLookupAttribute();
4293+
});
4294+
}
4295+
4296+
llvm::Expected<bool>
4297+
HasDynamicCallableAttributeRequest::evaluate(Evaluator &evaluator,
4298+
CanType ty) const {
4299+
return checkForDynamicAttribute<DynamicCallableAttr>(ty, [](Type type) {
4300+
return type->hasDynamicCallableAttribute();
4301+
});
4302+
}

0 commit comments

Comments
 (0)