Skip to content

Commit b6e6f69

Browse files
committed
IDE+Evaluator: converge multiple type relation checks into a single sema request, NFC
From libIDE, the utility functions will invoke the request in the implementation.
1 parent 1d6b991 commit b6e6f69

File tree

8 files changed

+124
-21
lines changed

8 files changed

+124
-21
lines changed

include/swift/Sema/IDETypeChecking.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ namespace swift {
5151

5252
bool canPossiblyEqual(Type T1, Type T2, DeclContext &DC);
5353

54-
bool canPossiblyConvertTo(Type T1, Type T2, DeclContext &DC);
55-
5654
void collectDefaultImplementationForProtocolMembers(ProtocolDecl *PD,
5755
llvm::SmallDenseMap<ValueDecl*, ValueDecl*> &DefaultMap);
5856

include/swift/Sema/IDETypeCheckingRequestIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717
SWIFT_TYPEID(IsDeclApplicableRequest)
18+
SWIFT_TYPEID(TypeRelationCheckRequest)

include/swift/Sema/IDETypeCheckingRequests.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,83 @@ class IsDeclApplicableRequest:
8383
SourceLoc getNearestLoc() const { return SourceLoc(); };
8484
};
8585

86+
//----------------------------------------------------------------------------//
87+
// Type relation checking
88+
//----------------------------------------------------------------------------//
89+
enum class TypeRelation: uint8_t {
90+
EqualTo,
91+
PossiblyEqualTo,
92+
ConvertTo,
93+
};
94+
95+
struct TypeRelationCheckInput {
96+
DeclContext *DC;
97+
Type FirstType;
98+
Type SecondType;
99+
TypeRelation Relation;
100+
bool OpenArchetypes;
101+
102+
TypeRelationCheckInput(DeclContext *DC, Type FirstType, Type SecondType,
103+
TypeRelation Relation, bool OpenArchetypes = true):
104+
DC(DC), FirstType(FirstType), SecondType(SecondType), Relation(Relation),
105+
OpenArchetypes(OpenArchetypes) {}
106+
107+
friend llvm::hash_code hash_value(const TypeRelationCheckInput &TI) {
108+
return hash_combine(hash_value(TI.FirstType.getPointer()),
109+
hash_value(TI.SecondType.getPointer()),
110+
hash_value(TI.Relation),
111+
hash_value(TI.OpenArchetypes));
112+
}
113+
114+
friend bool operator==(const TypeRelationCheckInput &lhs,
115+
const TypeRelationCheckInput &rhs) {
116+
return lhs.FirstType.getPointer() == rhs.FirstType.getPointer() &&
117+
lhs.SecondType.getPointer() == rhs.SecondType.getPointer() &&
118+
lhs.Relation == rhs.Relation &&
119+
lhs.OpenArchetypes == rhs.OpenArchetypes;
120+
}
121+
122+
friend bool operator!=(const TypeRelationCheckInput &lhs,
123+
const TypeRelationCheckInput &rhs) {
124+
return !(lhs == rhs);
125+
}
126+
127+
friend void simple_display(llvm::raw_ostream &out,
128+
const TypeRelationCheckInput &owner) {
129+
out << "Check if ";
130+
simple_display(out, owner.FirstType);
131+
out << " is ";
132+
switch(owner.Relation) {
133+
#define CASE(NAME) case TypeRelation::NAME: out << #NAME << " "; break;
134+
CASE(EqualTo)
135+
CASE(PossiblyEqualTo)
136+
CASE(ConvertTo)
137+
#undef CASE
138+
}
139+
simple_display(out, owner.SecondType);
140+
}
141+
};
142+
143+
class TypeRelationCheckRequest:
144+
public SimpleRequest<TypeRelationCheckRequest,
145+
bool(TypeRelationCheckInput),
146+
CacheKind::Cached> {
147+
public:
148+
using SimpleRequest::SimpleRequest;
149+
150+
private:
151+
friend SimpleRequest;
152+
153+
// Evaluation.
154+
llvm::Expected<bool> evaluate(Evaluator &evaluator,
155+
TypeRelationCheckInput Owner) const;
156+
157+
public:
158+
// Caching
159+
bool isCached() const { return true; }
160+
// Source location
161+
SourceLoc getNearestLoc() const { return SourceLoc(); };
162+
};
86163

87164
/// The zone number for the IDE.
88165
#define SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE 97

lib/IDE/IDETypeChecking.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ struct SynthesizedExtensionAnalyzer::Implementation {
327327
case RequirementKind::Superclass:
328328
// FIXME: This could be more accurate; check
329329
// conformance instead of subtyping
330-
if (!canPossiblyConvertTo(First, Second, *DC))
330+
if (!isConvertibleTo(First, Second, /*openArchetypes=*/true, *DC))
331331
return true;
332332
else if (!isConvertibleTo(First, Second, /*openArchetypes=*/false,
333333
*DC))
@@ -751,3 +751,23 @@ bool swift::isMemberDeclApplied(const DeclContext *DC, Type BaseTy,
751751
return evaluateOrDefault(DC->getASTContext().evaluator,
752752
IsDeclApplicableRequest(DeclApplicabilityOwner(DC, BaseTy, VD)), false);
753753
}
754+
755+
bool swift::canPossiblyEqual(Type T1, Type T2, DeclContext &DC) {
756+
return evaluateOrDefault(DC.getASTContext().evaluator,
757+
TypeRelationCheckRequest(TypeRelationCheckInput(&DC, T1, T2,
758+
TypeRelation::PossiblyEqualTo, true)), false);
759+
}
760+
761+
762+
bool swift::isEqual(Type T1, Type T2, DeclContext &DC) {
763+
return evaluateOrDefault(DC.getASTContext().evaluator,
764+
TypeRelationCheckRequest(TypeRelationCheckInput(&DC, T1, T2,
765+
TypeRelation::EqualTo, true)), false);
766+
}
767+
768+
bool swift::isConvertibleTo(Type T1, Type T2, bool openArchetypes,
769+
DeclContext &DC) {
770+
return evaluateOrDefault(DC.getASTContext().evaluator,
771+
TypeRelationCheckRequest(TypeRelationCheckInput(&DC, T1, T2,
772+
TypeRelation::ConvertTo, openArchetypes)), false);
773+
}

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3769,31 +3769,14 @@ bool swift::areGenericRequirementsSatisfied(
37693769
return CS.solveSingle().hasValue();
37703770
}
37713771

3772-
static bool canSatisfy(Type type1, Type type2, bool openArchetypes,
3772+
bool swift::canSatisfy(Type type1, Type type2, bool openArchetypes,
37733773
ConstraintKind kind, DeclContext *dc) {
37743774
std::unique_ptr<TypeChecker> CreatedTC;
37753775
auto &TC = TypeChecker::createForContext(dc->getASTContext());
37763776
return TC.typesSatisfyConstraint(type1, type2, openArchetypes, kind, dc,
37773777
/*unwrappedIUO=*/nullptr);
37783778
}
37793779

3780-
bool swift::canPossiblyEqual(Type T1, Type T2, DeclContext &DC) {
3781-
return canSatisfy(T1, T2, true, ConstraintKind::Bind, &DC);
3782-
}
3783-
3784-
bool swift::canPossiblyConvertTo(Type T1, Type T2, DeclContext &DC) {
3785-
return canSatisfy(T1, T2, true, ConstraintKind::Conversion, &DC);
3786-
}
3787-
3788-
bool swift::isEqual(Type T1, Type T2, DeclContext &DC) {
3789-
return T1->isEqual(T2);
3790-
}
3791-
3792-
bool swift::isConvertibleTo(Type T1, Type T2, bool openArchetypes,
3793-
DeclContext &DC) {
3794-
return canSatisfy(T1, T2, openArchetypes, ConstraintKind::Conversion, &DC);
3795-
}
3796-
37973780
void swift::eraseOpenedExistentials(ConstraintSystem &CS, Expr *&expr) {
37983781
expr = expr->walk(SanitizeExpr(CS, /*eraseOEsOnly=*/true));
37993782
}

lib/Sema/IDETypeCheckingRequests.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "swift/Sema/IDETypeCheckingRequests.h"
1919
#include "swift/Subsystems.h"
2020
#include "TypeChecker.h"
21+
#include "ConstraintGraph.h"
22+
#include "ConstraintSystem.h"
2123

2224
using namespace swift;
2325

@@ -96,3 +98,22 @@ IsDeclApplicableRequest::evaluate(Evaluator &evaluator,
9698
llvm_unreachable("unhandled decl kind");
9799
}
98100
}
101+
102+
llvm::Expected<bool>
103+
TypeRelationCheckRequest::evaluate(Evaluator &evaluator,
104+
TypeRelationCheckInput Owner) const {
105+
Optional<constraints::ConstraintKind> CKind;
106+
switch (Owner.Relation) {
107+
case TypeRelation::EqualTo:
108+
return Owner.FirstType->isEqual(Owner.SecondType);
109+
case TypeRelation::PossiblyEqualTo:
110+
CKind = constraints::ConstraintKind::Bind;
111+
break;
112+
case TypeRelation::ConvertTo:
113+
CKind = constraints::ConstraintKind::Conversion;
114+
break;
115+
}
116+
assert(CKind.hasValue());
117+
return canSatisfy(Owner.FirstType, Owner.SecondType, Owner.OpenArchetypes,
118+
*CKind, Owner.DC);
119+
}

lib/Sema/TypeChecker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,6 +2172,8 @@ bool areGenericRequirementsSatisfied(const DeclContext *DC,
21722172
const SubstitutionMap &Substitutions,
21732173
bool isExtension);
21742174

2175+
bool canSatisfy(Type type1, Type type2, bool openArchetypes,
2176+
constraints::ConstraintKind kind, DeclContext *dc);
21752177
} // end namespace swift
21762178

21772179
#endif

tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,7 @@ static bool reportModuleDocInfo(CompilerInvocation Invocation,
969969
return true;
970970

971971
ASTContext &Ctx = CI.getASTContext();
972+
registerIDERequestFunctions(Ctx.evaluator);
972973
(void)createTypeChecker(Ctx);
973974

974975
SourceTextInfo IFaceInfo;

0 commit comments

Comments
 (0)