Skip to content

Commit 7658d63

Browse files
committed
IDE+Evaluator: refactor IDE type-checking utilities for subscript decl into requests
We used to have a function getRootAndResultTypeOfKeypathDynamicMember to return both the root and result type of a subscript. This patch splits the function into two functions returning root type and result type respectively. It also refactors the implementation into the evaluator model.
1 parent 68d25a2 commit 7658d63

10 files changed

+130
-47
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ SWIFT_TYPEID_NAMED(ValueDecl *, ValueDecl)
2020
SWIFT_TYPEID_NAMED(ProtocolDecl *, ProtocolDecl)
2121
SWIFT_TYPEID_NAMED(Decl *, Decl)
2222
SWIFT_TYPEID(Type)
23+
SWIFT_TYPEID(TypePair)
2324
SWIFT_TYPEID(PropertyWrapperBackingPropertyInfo)
2425
SWIFT_TYPEID(PropertyWrapperTypeInfo)
2526
SWIFT_TYPEID_NAMED(Optional<PropertyWrapperMutability>, PropertyWrapperMutability)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class Type;
2929
class VarDecl;
3030
class TypeAliasDecl;
3131
class Type;
32+
struct TypePair;
3233

3334
#define SWIFT_AST_TYPEID_ZONE 1
3435

include/swift/Sema/IDETypeChecking.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,10 @@ namespace swift {
234234
/// dynamic member lookup subscript, or \c None if it cannot be determined.
235235
///
236236
/// \param subscript The potential keypath dynamic member lookup subscript.
237-
/// \param DC The DeclContext from which the subscript is being referenced.
238-
Optional<std::pair<Type, Type>>
239-
getRootAndResultTypeOfKeypathDynamicMember(SubscriptDecl *subscript,
240-
const DeclContext *DC);
237+
Type getRootTypeOfKeypathDynamicMember(SubscriptDecl *subscript);
238+
239+
Type getResultTypeOfKeypathDynamicMember(SubscriptDecl *subscript);
240+
241241
/// Collect all the protocol requirements that a given declaration can
242242
/// provide default implementations for. VD is a declaration in extension
243243
/// declaration. Scratch is the buffer to collect those protocol

include/swift/Sema/IDETypeCheckingRequestIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@
1616
//===----------------------------------------------------------------------===//
1717
SWIFT_TYPEID(IsDeclApplicableRequest)
1818
SWIFT_TYPEID(TypeRelationCheckRequest)
19+
SWIFT_TYPEID(RootAndResultTypeOfKeypathDynamicMemberRequest)
20+
SWIFT_TYPEID(RootTypeOfKeypathDynamicMemberRequest)

include/swift/Sema/IDETypeCheckingRequests.h

Lines changed: 83 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,30 +92,57 @@ enum class TypeRelation: uint8_t {
9292
ConvertTo,
9393
};
9494

95+
struct TypePair {
96+
Type FirstTy;
97+
Type SecondTy;
98+
TypePair(Type FirstTy, Type SecondTy): FirstTy(FirstTy), SecondTy(SecondTy) {}
99+
TypePair(): TypePair(Type(), Type()) {}
100+
friend llvm::hash_code hash_value(const TypePair &TI) {
101+
return hash_combine(hash_value(TI.FirstTy.getPointer()),
102+
hash_value(TI.SecondTy.getPointer()));
103+
}
104+
105+
friend bool operator==(const TypePair &lhs,
106+
const TypePair &rhs) {
107+
return lhs.FirstTy.getPointer() == rhs.FirstTy.getPointer() &&
108+
lhs.SecondTy.getPointer() == rhs.SecondTy.getPointer();
109+
}
110+
111+
friend bool operator!=(const TypePair &lhs,
112+
const TypePair &rhs) {
113+
return !(lhs == rhs);
114+
}
115+
116+
friend void simple_display(llvm::raw_ostream &out,
117+
const TypePair &owner) {
118+
out << "<";
119+
simple_display(out, owner.FirstTy);
120+
out << ", ";
121+
simple_display(out, owner.SecondTy);
122+
out << ">";
123+
}
124+
};
125+
95126
struct TypeRelationCheckInput {
96127
DeclContext *DC;
97-
Type FirstType;
98-
Type SecondType;
128+
TypePair Pair;
99129
TypeRelation Relation;
100130
bool OpenArchetypes;
101131

102132
TypeRelationCheckInput(DeclContext *DC, Type FirstType, Type SecondType,
103133
TypeRelation Relation, bool OpenArchetypes = true):
104-
DC(DC), FirstType(FirstType), SecondType(SecondType), Relation(Relation),
134+
DC(DC), Pair(FirstType, SecondType), Relation(Relation),
105135
OpenArchetypes(OpenArchetypes) {}
106136

107137
friend llvm::hash_code hash_value(const TypeRelationCheckInput &TI) {
108-
return hash_combine(hash_value(TI.FirstType.getPointer()),
109-
hash_value(TI.SecondType.getPointer()),
138+
return hash_combine(hash_value(TI.Pair),
110139
hash_value(TI.Relation),
111140
hash_value(TI.OpenArchetypes));
112141
}
113142

114143
friend bool operator==(const TypeRelationCheckInput &lhs,
115144
const TypeRelationCheckInput &rhs) {
116-
return lhs.FirstType.getPointer() == rhs.FirstType.getPointer() &&
117-
lhs.SecondType.getPointer() == rhs.SecondType.getPointer() &&
118-
lhs.Relation == rhs.Relation &&
145+
return lhs.Pair == rhs.Pair && lhs.Relation == rhs.Relation &&
119146
lhs.OpenArchetypes == rhs.OpenArchetypes;
120147
}
121148

@@ -127,7 +154,7 @@ struct TypeRelationCheckInput {
127154
friend void simple_display(llvm::raw_ostream &out,
128155
const TypeRelationCheckInput &owner) {
129156
out << "Check if ";
130-
simple_display(out, owner.FirstType);
157+
simple_display(out, owner.Pair);
131158
out << " is ";
132159
switch(owner.Relation) {
133160
#define CASE(NAME) case TypeRelation::NAME: out << #NAME << " "; break;
@@ -136,7 +163,6 @@ struct TypeRelationCheckInput {
136163
CASE(ConvertTo)
137164
#undef CASE
138165
}
139-
simple_display(out, owner.SecondType);
140166
}
141167
};
142168

@@ -161,6 +187,53 @@ class TypeRelationCheckRequest:
161187
SourceLoc getNearestLoc() const { return SourceLoc(); };
162188
};
163189

190+
//----------------------------------------------------------------------------//
191+
// RootAndResultTypeOfKeypathDynamicMemberRequest
192+
//----------------------------------------------------------------------------//
193+
class RootAndResultTypeOfKeypathDynamicMemberRequest:
194+
public SimpleRequest<RootAndResultTypeOfKeypathDynamicMemberRequest,
195+
TypePair(SubscriptDecl*),
196+
CacheKind::Cached> {
197+
public:
198+
using SimpleRequest::SimpleRequest;
199+
200+
private:
201+
friend SimpleRequest;
202+
203+
// Evaluation.
204+
llvm::Expected<TypePair> evaluate(Evaluator &evaluator, SubscriptDecl* SD) const;
205+
206+
public:
207+
// Caching
208+
bool isCached() const { return true; }
209+
// Source location
210+
SourceLoc getNearestLoc() const { return SourceLoc(); };
211+
};
212+
213+
class RootTypeOfKeypathDynamicMemberRequest:
214+
public SimpleRequest<RootTypeOfKeypathDynamicMemberRequest,
215+
Type(SubscriptDecl*),
216+
/*Cached in the request above*/CacheKind::Uncached> {
217+
public:
218+
using SimpleRequest::SimpleRequest;
219+
220+
private:
221+
friend SimpleRequest;
222+
223+
// Evaluation.
224+
llvm::Expected<Type> evaluate(Evaluator &evaluator, SubscriptDecl* SD) const {
225+
return evaluateOrDefault(SD->getASTContext().evaluator,
226+
RootAndResultTypeOfKeypathDynamicMemberRequest{SD}, TypePair()).
227+
FirstTy;
228+
}
229+
230+
public:
231+
// Caching
232+
bool isCached() const { return true; }
233+
// Source location
234+
SourceLoc getNearestLoc() const { return SourceLoc(); };
235+
};
236+
164237
/// The zone number for the IDE.
165238
#define SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE 97
166239
#define SWIFT_TYPEID_ZONE SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE

lib/IDE/CodeCompletion.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,18 +1994,14 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19941994
// τ_1_0(U) => U }
19951995
auto subs = keyPathInfo.baseType->getMemberSubstitutions(SD);
19961996

1997-
// Extract the root and result type of the KeyPath type in the parameter.
1998-
// i.e. 'T' and 'U'
1999-
auto rootAndResult =
2000-
getRootAndResultTypeOfKeypathDynamicMember(SD, CurrDeclContext);
2001-
20021997
// If the keyPath result type has type parameters, that might affect the
20031998
// subscript result type.
2004-
auto keyPathResultTy = rootAndResult->second->mapTypeOutOfContext();
1999+
auto keyPathResultTy = getResultTypeOfKeypathDynamicMember(SD)->
2000+
mapTypeOutOfContext();
20052001
if (keyPathResultTy->hasTypeParameter()) {
2006-
auto keyPathRootTy =
2007-
rootAndResult->first.subst(QueryTypeSubstitutionMap{subs},
2008-
LookUpConformanceInModule(CurrModule));
2002+
auto keyPathRootTy = getRootTypeOfKeypathDynamicMember(SD).
2003+
subst(QueryTypeSubstitutionMap{subs},
2004+
LookUpConformanceInModule(CurrModule));
20092005

20102006
// The result type of the VD.
20112007
// i.e. 'Circle.center' => 'Point'.

lib/IDE/IDETypeChecking.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,3 +771,14 @@ bool swift::isConvertibleTo(Type T1, Type T2, bool openArchetypes,
771771
TypeRelationCheckRequest(TypeRelationCheckInput(&DC, T1, T2,
772772
TypeRelation::ConvertTo, openArchetypes)), false);
773773
}
774+
775+
Type swift::getRootTypeOfKeypathDynamicMember(SubscriptDecl *SD) {
776+
return evaluateOrDefault(SD->getASTContext().evaluator,
777+
RootTypeOfKeypathDynamicMemberRequest{SD}, Type());
778+
}
779+
780+
Type swift::getResultTypeOfKeypathDynamicMember(SubscriptDecl *SD) {
781+
return evaluateOrDefault(SD->getASTContext().evaluator,
782+
RootAndResultTypeOfKeypathDynamicMemberRequest{SD}, TypePair()).
783+
SecondTy;
784+
}

lib/Sema/IDETypeCheckingRequests.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ TypeRelationCheckRequest::evaluate(Evaluator &evaluator,
105105
Optional<constraints::ConstraintKind> CKind;
106106
switch (Owner.Relation) {
107107
case TypeRelation::EqualTo:
108-
return Owner.FirstType->isEqual(Owner.SecondType);
108+
return Owner.Pair.FirstTy->isEqual(Owner.Pair.SecondTy);
109109
case TypeRelation::PossiblyEqualTo:
110110
CKind = constraints::ConstraintKind::Bind;
111111
break;
@@ -114,6 +114,24 @@ TypeRelationCheckRequest::evaluate(Evaluator &evaluator,
114114
break;
115115
}
116116
assert(CKind.hasValue());
117-
return canSatisfy(Owner.FirstType, Owner.SecondType, Owner.OpenArchetypes,
117+
return canSatisfy(Owner.Pair.FirstTy, Owner.Pair.SecondTy, Owner.OpenArchetypes,
118118
*CKind, Owner.DC);
119119
}
120+
121+
llvm::Expected<TypePair>
122+
RootAndResultTypeOfKeypathDynamicMemberRequest::evaluate(Evaluator &evaluator,
123+
SubscriptDecl *subscript) const {
124+
auto &TC = TypeChecker::createForContext(subscript->getASTContext());
125+
126+
if (!isValidKeyPathDynamicMemberLookup(subscript, TC))
127+
return TypePair();
128+
129+
const auto *param = subscript->getIndices()->get(0);
130+
auto keyPathType = param->getType()->getAs<BoundGenericType>();
131+
if (!keyPathType)
132+
return TypePair();
133+
auto genericArgs = keyPathType->getGenericArgs();
134+
assert(!genericArgs.empty() && genericArgs.size() == 2 &&
135+
"invalid keypath dynamic member");
136+
return TypePair(genericArgs[0], genericArgs[1]);
137+
}

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -977,11 +977,10 @@ static void lookupVisibleDynamicMemberLookupDecls(
977977
if (!subscript)
978978
continue;
979979

980-
auto rootAndResult =
981-
getRootAndResultTypeOfKeypathDynamicMember(subscript, dc);
982-
if (!rootAndResult)
980+
auto rootType = evaluateOrDefault(subscript->getASTContext().evaluator,
981+
RootTypeOfKeypathDynamicMemberRequest{subscript}, Type());
982+
if (rootType.isNull())
983983
continue;
984-
auto rootType = rootAndResult->first;
985984

986985
auto subs =
987986
baseType->getMemberSubstitutionMap(dc->getParentModule(), subscript);

lib/Sema/TypeCheckAttr.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -972,24 +972,6 @@ bool swift::isValidKeyPathDynamicMemberLookup(SubscriptDecl *decl,
972972
return false;
973973
}
974974

975-
Optional<std::pair<Type, Type>>
976-
swift::getRootAndResultTypeOfKeypathDynamicMember(SubscriptDecl *subscript,
977-
const DeclContext *DC) {
978-
auto &TC = TypeChecker::createForContext(DC->getASTContext());
979-
980-
if (!isValidKeyPathDynamicMemberLookup(subscript, TC))
981-
return None;
982-
983-
const auto *param = subscript->getIndices()->get(0);
984-
auto keyPathType = param->getType()->getAs<BoundGenericType>();
985-
if (!keyPathType)
986-
return None;
987-
auto genericArgs = keyPathType->getGenericArgs();
988-
assert(!genericArgs.empty() && genericArgs.size() == 2 &&
989-
"invalid keypath dynamic member");
990-
return std::pair<Type, Type>{genericArgs[0], genericArgs[1]};
991-
}
992-
993975
/// The @dynamicMemberLookup attribute is only allowed on types that have at
994976
/// least one subscript member declared like this:
995977
///

0 commit comments

Comments
 (0)