Skip to content

Commit 36cecb4

Browse files
committed
Requestify hasDynamicMemberLookupAttribute for Sema too
Previously we had a request for this in IDETypeChecking, but this wasn't used for queries made from Sema. Move the request into Sema, and move `hasDynamicMemberLookupAttribute` onto TypeBase.
1 parent d3da328 commit 36cecb4

15 files changed

+100
-132
lines changed

include/swift/AST/Type.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,9 @@ class Type {
371371
void operator!=(Type T) const = delete;
372372
};
373373

374+
/// Extract the source location from a given type.
375+
SourceLoc extractNearestSourceLoc(Type ty);
376+
374377
/// CanType - This is a Type that is statically known to be canonical. To get
375378
/// one of these, use Type->getCanonicalType(). Since all CanType's can be used
376379
/// as 'Type' (they just don't have sugar) we derive from Type.

include/swift/AST/TypeCheckRequests.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,6 +1968,29 @@ class TypeCheckSourceFileRequest :
19681968
void cacheResult(bool result) const;
19691969
};
19701970

1971+
/// Computes whether the specified type or a super-class/super-protocol has the
1972+
/// @dynamicMemberLookup attribute on it.
1973+
class HasDynamicMemberLookupAttributeRequest
1974+
: public SimpleRequest<HasDynamicMemberLookupAttributeRequest,
1975+
bool(CanType), CacheKind::Cached> {
1976+
public:
1977+
using SimpleRequest::SimpleRequest;
1978+
1979+
private:
1980+
friend SimpleRequest;
1981+
1982+
// Evaluation.
1983+
llvm::Expected<bool> evaluate(Evaluator &evaluator, CanType ty) const;
1984+
1985+
public:
1986+
bool isCached() const {
1987+
// Don't cache types containing type variables, as they must not outlive
1988+
// the constraint system that created them.
1989+
auto ty = std::get<0>(getStorage());
1990+
return !ty->hasTypeVariable();
1991+
}
1992+
};
1993+
19711994
// Allow AnyValue to compare two Type values, even though Type doesn't
19721995
// support ==.
19731996
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ SWIFT_REQUEST(TypeChecker, HasCircularInheritedProtocolsRequest,
7373
bool(ProtocolDecl *), Cached, NoLocationInfo)
7474
SWIFT_REQUEST(TypeChecker, HasCircularRawValueRequest,
7575
bool(EnumDecl *), Cached, NoLocationInfo)
76+
SWIFT_REQUEST(TypeChecker, HasDynamicMemberLookupAttributeRequest,
77+
bool(CanType), Cached, NoLocationInfo)
7678
SWIFT_REQUEST(TypeChecker, InferredGenericSignatureRequest,
7779
GenericSignature (ModuleDecl *, GenericSignatureImpl *,
7880
GenericParamList *,

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,10 @@ class alignas(1 << TypeAlignInBits) TypeBase {
829829
/// check access control.
830830
bool isCallableNominalType(DeclContext *dc);
831831

832+
/// Return true if the specified type or a super-class/super-protocol has the
833+
/// @dynamicMemberLookup attribute on it.
834+
bool hasDynamicMemberLookupAttribute();
835+
832836
/// Retrieve the superclass of this type.
833837
///
834838
/// \param useArchetypes Whether to use context archetypes for outer generic

include/swift/Sema/IDETypeChecking.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,6 @@ namespace swift {
232232
/// written by the user; this performs the reverse transformation.
233233
OriginalArgumentList getOriginalArgumentList(Expr *expr);
234234

235-
/// Return true if the specified type or a super-class/super-protocol has the
236-
/// @dynamicMemberLookup attribute on it.
237-
bool hasDynamicMemberLookupAttribute(Type type);
238-
239235
/// Returns the root type and result type of the keypath type in a keypath
240236
/// dynamic member lookup subscript, or \c None if it cannot be determined.
241237
///

include/swift/Sema/IDETypeCheckingRequestIDZone.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18-
SWIFT_REQUEST(IDETypeChecking, HasDynamicMemberLookupAttributeRequest,
19-
bool(TypeBase *), Cached, NoLocationInfo)
2018
SWIFT_REQUEST(IDETypeChecking, IsDeclApplicableRequest,
2119
bool(DeclApplicabilityOwner), Cached, NoLocationInfo)
2220
SWIFT_REQUEST(IDETypeChecking, RootAndResultTypeOfKeypathDynamicMemberRequest,

include/swift/Sema/IDETypeCheckingRequests.h

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -227,29 +227,6 @@ class RootTypeOfKeypathDynamicMemberRequest:
227227
SourceLoc getNearestLoc() const { return SourceLoc(); };
228228
};
229229

230-
//----------------------------------------------------------------------------//
231-
// HasDynamicMemberLookupAttributeRequest
232-
//----------------------------------------------------------------------------//
233-
class HasDynamicMemberLookupAttributeRequest:
234-
public SimpleRequest<HasDynamicMemberLookupAttributeRequest,
235-
bool(TypeBase*),
236-
CacheKind::Cached> {
237-
public:
238-
using SimpleRequest::SimpleRequest;
239-
240-
private:
241-
friend SimpleRequest;
242-
243-
// Evaluation.
244-
llvm::Expected<bool> evaluate(Evaluator &evaluator, TypeBase *ty) const;
245-
246-
public:
247-
// Caching
248-
bool isCached() const { return true; }
249-
// Source location
250-
SourceLoc getNearestLoc() const { return SourceLoc(); };
251-
};
252-
253230
/// The zone number for the IDE.
254231
#define SWIFT_TYPEID_ZONE IDETypeChecking
255232
#define SWIFT_TYPEID_HEADER "swift/Sema/IDETypeCheckingRequestIDZone.def"

lib/AST/Type.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,13 @@ bool TypeBase::isCallableNominalType(DeclContext *dc) {
14981498
IsCallableNominalTypeRequest{canTy, dc}, false);
14991499
}
15001500

1501+
bool TypeBase::hasDynamicMemberLookupAttribute() {
1502+
auto canTy = getCanonicalType();
1503+
auto &ctx = canTy->getASTContext();
1504+
return evaluateOrDefault(
1505+
ctx.evaluator, HasDynamicMemberLookupAttributeRequest{canTy}, false);
1506+
}
1507+
15011508
Type TypeBase::getSuperclass(bool useArchetypes) {
15021509
auto *nominalDecl = getAnyNominal();
15031510
auto *classDecl = dyn_cast_or_null<ClassDecl>(nominalDecl);
@@ -4857,3 +4864,10 @@ SILFunctionType::withSubstitutions(SubstitutionMap subs) const {
48574864
subs, isGenericSignatureImplied(),
48584865
const_cast<SILFunctionType*>(this)->getASTContext());
48594866
}
4867+
4868+
SourceLoc swift::extractNearestSourceLoc(Type ty) {
4869+
if (auto nominal = ty->getAnyNominal())
4870+
return extractNearestSourceLoc(nominal);
4871+
4872+
return SourceLoc();
4873+
}

lib/IDE/IDETypeChecking.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -759,8 +759,3 @@ Type swift::getResultTypeOfKeypathDynamicMember(SubscriptDecl *SD) {
759759
RootAndResultTypeOfKeypathDynamicMemberRequest{SD}, TypePair()).
760760
SecondTy;
761761
}
762-
763-
bool swift::hasDynamicMemberLookupAttribute(Type ty) {
764-
return evaluateOrDefault(ty->getASTContext().evaluator,
765-
HasDynamicMemberLookupAttributeRequest{ty.getPointer()}, false);
766-
}

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -5186,85 +5186,6 @@ ConstraintSystem::simplifyFunctionComponentConstraint(
51865186
return SolutionKind::Solved;
51875187
}
51885188

5189-
/// Return true if the specified type or a super-class/super-protocol has the
5190-
/// @dynamicMemberLookup attribute on it. This implementation is not
5191-
/// particularly fast in the face of deep class hierarchies or lots of protocol
5192-
/// conformances, but this is fine because it doesn't get invoked in the normal
5193-
/// name lookup path (only when lookup is about to fail).
5194-
bool swift::hasDynamicMemberLookupAttribute(Type type,
5195-
llvm::DenseMap<CanType, bool> &DynamicMemberLookupCache) {
5196-
auto canType = type->getCanonicalType();
5197-
auto it = DynamicMemberLookupCache.find(canType);
5198-
if (it != DynamicMemberLookupCache.end()) return it->second;
5199-
5200-
// Calculate @dynamicMemberLookup attribute for composite types with multiple
5201-
// components (protocol composition types and archetypes).
5202-
auto calculateForComponentTypes =
5203-
[&](ArrayRef<Type> componentTypes) -> bool {
5204-
for (auto componentType : componentTypes)
5205-
if (hasDynamicMemberLookupAttribute(componentType,
5206-
DynamicMemberLookupCache))
5207-
return true;
5208-
return false;
5209-
};
5210-
5211-
auto calculate = [&]() -> bool {
5212-
// If this is an archetype type, check if any types it conforms to
5213-
// (superclass or protocols) have the attribute.
5214-
if (auto archetype = dyn_cast<ArchetypeType>(canType)) {
5215-
SmallVector<Type, 2> componentTypes;
5216-
for (auto protocolDecl : archetype->getConformsTo())
5217-
componentTypes.push_back(protocolDecl->getDeclaredType());
5218-
if (auto superclass = archetype->getSuperclass())
5219-
componentTypes.push_back(superclass);
5220-
return calculateForComponentTypes(componentTypes);
5221-
}
5222-
5223-
// If this is a protocol composition, check if any of its members have the
5224-
// attribute.
5225-
if (auto protocolComp = dyn_cast<ProtocolCompositionType>(canType))
5226-
return calculateForComponentTypes(protocolComp->getMembers());
5227-
5228-
// Otherwise, this must be a nominal type.
5229-
// Dynamic member lookup doesn't work for tuples, etc.
5230-
auto nominal = canType->getAnyNominal();
5231-
if (!nominal) return false;
5232-
5233-
// If this type conforms to a protocol with the attribute, then return true.
5234-
for (auto p : nominal->getAllProtocols())
5235-
if (p->getAttrs().hasAttribute<DynamicMemberLookupAttr>())
5236-
return true;
5237-
5238-
// Walk superclasses, if present.
5239-
llvm::SmallPtrSet<const NominalTypeDecl*, 8> visitedDecls;
5240-
while (1) {
5241-
// If we found a circular parent class chain, reject this.
5242-
if (!visitedDecls.insert(nominal).second)
5243-
return false;
5244-
5245-
// If this type has the attribute on it, then yes!
5246-
if (nominal->getAttrs().hasAttribute<DynamicMemberLookupAttr>())
5247-
return true;
5248-
5249-
// If this is a class with a super class, check super classes as well.
5250-
if (auto *cd = dyn_cast<ClassDecl>(nominal)) {
5251-
if (auto superClass = cd->getSuperclassDecl()) {
5252-
nominal = superClass;
5253-
continue;
5254-
}
5255-
}
5256-
5257-
return false;
5258-
}
5259-
};
5260-
5261-
auto result = calculate();
5262-
// Cache the result if the type does not contain type variables.
5263-
if (!type->hasTypeVariable())
5264-
DynamicMemberLookupCache[canType] = result;
5265-
return result;
5266-
}
5267-
52685189
static bool isForKeyPathSubscript(ConstraintSystem &cs,
52695190
ConstraintLocator *locator) {
52705191
if (!locator || !locator->getAnchor())
@@ -5738,9 +5659,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
57385659
// as representing "dynamic lookup" unless it's a direct call
57395660
// to such subscript (in that case label is expected to match).
57405661
if (auto *subscript = dyn_cast<SubscriptDecl>(cand)) {
5741-
if (memberLocator &&
5742-
::hasDynamicMemberLookupAttribute(instanceTy,
5743-
DynamicMemberLookupCache) &&
5662+
if (memberLocator && instanceTy->hasDynamicMemberLookupAttribute() &&
57445663
isValidKeyPathDynamicMemberLookup(subscript)) {
57455664
auto info = getArgumentInfo(memberLocator);
57465665

@@ -5829,7 +5748,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
58295748
// parameter.
58305749
if (constraintKind == ConstraintKind::ValueMember &&
58315750
memberName.isSimpleName() && !memberName.isSpecial() &&
5832-
::hasDynamicMemberLookupAttribute(instanceTy, DynamicMemberLookupCache)) {
5751+
instanceTy->hasDynamicMemberLookupAttribute()) {
58335752
const auto &candidates = result.ViableCandidates;
58345753

58355754
if ((candidates.empty() ||

0 commit comments

Comments
 (0)