Skip to content

Commit f1e690c

Browse files
authored
Merge pull request swiftlang#28775 from hamishknight/dynamic-lookup-attr-req
Requestify hasDynamicMemberLookupAttribute for Sema too
2 parents 4576c88 + 36cecb4 commit f1e690c

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
@@ -5192,85 +5192,6 @@ ConstraintSystem::simplifyFunctionComponentConstraint(
51925192
return SolutionKind::Solved;
51935193
}
51945194

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

@@ -5835,7 +5754,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
58355754
// parameter.
58365755
if (constraintKind == ConstraintKind::ValueMember &&
58375756
memberName.isSimpleName() && !memberName.isSpecial() &&
5838-
::hasDynamicMemberLookupAttribute(instanceTy, DynamicMemberLookupCache)) {
5757+
instanceTy->hasDynamicMemberLookupAttribute()) {
58395758
const auto &candidates = result.ViableCandidates;
58405759

58415760
if ((candidates.empty() ||

0 commit comments

Comments
 (0)