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.
This commit is contained in:
Xi Ge
2019-07-24 12:16:42 -07:00
parent 1d6b991086
commit b6e6f69e80
8 changed files with 124 additions and 21 deletions

View File

@@ -51,8 +51,6 @@ namespace swift {
bool canPossiblyEqual(Type T1, Type T2, DeclContext &DC); bool canPossiblyEqual(Type T1, Type T2, DeclContext &DC);
bool canPossiblyConvertTo(Type T1, Type T2, DeclContext &DC);
void collectDefaultImplementationForProtocolMembers(ProtocolDecl *PD, void collectDefaultImplementationForProtocolMembers(ProtocolDecl *PD,
llvm::SmallDenseMap<ValueDecl*, ValueDecl*> &DefaultMap); llvm::SmallDenseMap<ValueDecl*, ValueDecl*> &DefaultMap);

View File

@@ -15,3 +15,4 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
SWIFT_TYPEID(IsDeclApplicableRequest) SWIFT_TYPEID(IsDeclApplicableRequest)
SWIFT_TYPEID(TypeRelationCheckRequest)

View File

@@ -83,6 +83,83 @@ public:
SourceLoc getNearestLoc() const { return SourceLoc(); }; SourceLoc getNearestLoc() const { return SourceLoc(); };
}; };
//----------------------------------------------------------------------------//
// Type relation checking
//----------------------------------------------------------------------------//
enum class TypeRelation: uint8_t {
EqualTo,
PossiblyEqualTo,
ConvertTo,
};
struct TypeRelationCheckInput {
DeclContext *DC;
Type FirstType;
Type SecondType;
TypeRelation Relation;
bool OpenArchetypes;
TypeRelationCheckInput(DeclContext *DC, Type FirstType, Type SecondType,
TypeRelation Relation, bool OpenArchetypes = true):
DC(DC), FirstType(FirstType), SecondType(SecondType), Relation(Relation),
OpenArchetypes(OpenArchetypes) {}
friend llvm::hash_code hash_value(const TypeRelationCheckInput &TI) {
return hash_combine(hash_value(TI.FirstType.getPointer()),
hash_value(TI.SecondType.getPointer()),
hash_value(TI.Relation),
hash_value(TI.OpenArchetypes));
}
friend bool operator==(const TypeRelationCheckInput &lhs,
const TypeRelationCheckInput &rhs) {
return lhs.FirstType.getPointer() == rhs.FirstType.getPointer() &&
lhs.SecondType.getPointer() == rhs.SecondType.getPointer() &&
lhs.Relation == rhs.Relation &&
lhs.OpenArchetypes == rhs.OpenArchetypes;
}
friend bool operator!=(const TypeRelationCheckInput &lhs,
const TypeRelationCheckInput &rhs) {
return !(lhs == rhs);
}
friend void simple_display(llvm::raw_ostream &out,
const TypeRelationCheckInput &owner) {
out << "Check if ";
simple_display(out, owner.FirstType);
out << " is ";
switch(owner.Relation) {
#define CASE(NAME) case TypeRelation::NAME: out << #NAME << " "; break;
CASE(EqualTo)
CASE(PossiblyEqualTo)
CASE(ConvertTo)
#undef CASE
}
simple_display(out, owner.SecondType);
}
};
class TypeRelationCheckRequest:
public SimpleRequest<TypeRelationCheckRequest,
bool(TypeRelationCheckInput),
CacheKind::Cached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<bool> evaluate(Evaluator &evaluator,
TypeRelationCheckInput Owner) const;
public:
// Caching
bool isCached() const { return true; }
// Source location
SourceLoc getNearestLoc() const { return SourceLoc(); };
};
/// The zone number for the IDE. /// The zone number for the IDE.
#define SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE 97 #define SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE 97

View File

@@ -327,7 +327,7 @@ struct SynthesizedExtensionAnalyzer::Implementation {
case RequirementKind::Superclass: case RequirementKind::Superclass:
// FIXME: This could be more accurate; check // FIXME: This could be more accurate; check
// conformance instead of subtyping // conformance instead of subtyping
if (!canPossiblyConvertTo(First, Second, *DC)) if (!isConvertibleTo(First, Second, /*openArchetypes=*/true, *DC))
return true; return true;
else if (!isConvertibleTo(First, Second, /*openArchetypes=*/false, else if (!isConvertibleTo(First, Second, /*openArchetypes=*/false,
*DC)) *DC))
@@ -751,3 +751,23 @@ bool swift::isMemberDeclApplied(const DeclContext *DC, Type BaseTy,
return evaluateOrDefault(DC->getASTContext().evaluator, return evaluateOrDefault(DC->getASTContext().evaluator,
IsDeclApplicableRequest(DeclApplicabilityOwner(DC, BaseTy, VD)), false); IsDeclApplicableRequest(DeclApplicabilityOwner(DC, BaseTy, VD)), false);
} }
bool swift::canPossiblyEqual(Type T1, Type T2, DeclContext &DC) {
return evaluateOrDefault(DC.getASTContext().evaluator,
TypeRelationCheckRequest(TypeRelationCheckInput(&DC, T1, T2,
TypeRelation::PossiblyEqualTo, true)), false);
}
bool swift::isEqual(Type T1, Type T2, DeclContext &DC) {
return evaluateOrDefault(DC.getASTContext().evaluator,
TypeRelationCheckRequest(TypeRelationCheckInput(&DC, T1, T2,
TypeRelation::EqualTo, true)), false);
}
bool swift::isConvertibleTo(Type T1, Type T2, bool openArchetypes,
DeclContext &DC) {
return evaluateOrDefault(DC.getASTContext().evaluator,
TypeRelationCheckRequest(TypeRelationCheckInput(&DC, T1, T2,
TypeRelation::ConvertTo, openArchetypes)), false);
}

View File

@@ -3769,7 +3769,7 @@ bool swift::areGenericRequirementsSatisfied(
return CS.solveSingle().hasValue(); return CS.solveSingle().hasValue();
} }
static bool canSatisfy(Type type1, Type type2, bool openArchetypes, bool swift::canSatisfy(Type type1, Type type2, bool openArchetypes,
ConstraintKind kind, DeclContext *dc) { ConstraintKind kind, DeclContext *dc) {
std::unique_ptr<TypeChecker> CreatedTC; std::unique_ptr<TypeChecker> CreatedTC;
auto &TC = TypeChecker::createForContext(dc->getASTContext()); auto &TC = TypeChecker::createForContext(dc->getASTContext());
@@ -3777,23 +3777,6 @@ static bool canSatisfy(Type type1, Type type2, bool openArchetypes,
/*unwrappedIUO=*/nullptr); /*unwrappedIUO=*/nullptr);
} }
bool swift::canPossiblyEqual(Type T1, Type T2, DeclContext &DC) {
return canSatisfy(T1, T2, true, ConstraintKind::Bind, &DC);
}
bool swift::canPossiblyConvertTo(Type T1, Type T2, DeclContext &DC) {
return canSatisfy(T1, T2, true, ConstraintKind::Conversion, &DC);
}
bool swift::isEqual(Type T1, Type T2, DeclContext &DC) {
return T1->isEqual(T2);
}
bool swift::isConvertibleTo(Type T1, Type T2, bool openArchetypes,
DeclContext &DC) {
return canSatisfy(T1, T2, openArchetypes, ConstraintKind::Conversion, &DC);
}
void swift::eraseOpenedExistentials(ConstraintSystem &CS, Expr *&expr) { void swift::eraseOpenedExistentials(ConstraintSystem &CS, Expr *&expr) {
expr = expr->walk(SanitizeExpr(CS, /*eraseOEsOnly=*/true)); expr = expr->walk(SanitizeExpr(CS, /*eraseOEsOnly=*/true));
} }

View File

@@ -18,6 +18,8 @@
#include "swift/Sema/IDETypeCheckingRequests.h" #include "swift/Sema/IDETypeCheckingRequests.h"
#include "swift/Subsystems.h" #include "swift/Subsystems.h"
#include "TypeChecker.h" #include "TypeChecker.h"
#include "ConstraintGraph.h"
#include "ConstraintSystem.h"
using namespace swift; using namespace swift;
@@ -96,3 +98,22 @@ IsDeclApplicableRequest::evaluate(Evaluator &evaluator,
llvm_unreachable("unhandled decl kind"); llvm_unreachable("unhandled decl kind");
} }
} }
llvm::Expected<bool>
TypeRelationCheckRequest::evaluate(Evaluator &evaluator,
TypeRelationCheckInput Owner) const {
Optional<constraints::ConstraintKind> CKind;
switch (Owner.Relation) {
case TypeRelation::EqualTo:
return Owner.FirstType->isEqual(Owner.SecondType);
case TypeRelation::PossiblyEqualTo:
CKind = constraints::ConstraintKind::Bind;
break;
case TypeRelation::ConvertTo:
CKind = constraints::ConstraintKind::Conversion;
break;
}
assert(CKind.hasValue());
return canSatisfy(Owner.FirstType, Owner.SecondType, Owner.OpenArchetypes,
*CKind, Owner.DC);
}

View File

@@ -2172,6 +2172,8 @@ bool areGenericRequirementsSatisfied(const DeclContext *DC,
const SubstitutionMap &Substitutions, const SubstitutionMap &Substitutions,
bool isExtension); bool isExtension);
bool canSatisfy(Type type1, Type type2, bool openArchetypes,
constraints::ConstraintKind kind, DeclContext *dc);
} // end namespace swift } // end namespace swift
#endif #endif

View File

@@ -969,6 +969,7 @@ static bool reportModuleDocInfo(CompilerInvocation Invocation,
return true; return true;
ASTContext &Ctx = CI.getASTContext(); ASTContext &Ctx = CI.getASTContext();
registerIDERequestFunctions(Ctx.evaluator);
(void)createTypeChecker(Ctx); (void)createTypeChecker(Ctx);
SourceTextInfo IFaceInfo; SourceTextInfo IFaceInfo;