Skip to content

Commit 77ba3a2

Browse files
committed
IDE+Evaluator: refactor the implementation of two type checker utilities to evaluator requests. NFC
IDE functionality needs some internal type checking logics, e.g. checking whether an extension is applicable to a concrete type. We used to directly expose an header from sema called IDETypeChecking.h so that IDE functionalities could invoke these APIs. The goal of the commit and following commits is to expose evaluator requests instead of directly exposing function entry points from sema so that we could later move IDETypeChecking.h to libIDE and implement these functions by internally evaluating these requests.
1 parent be609e8 commit 77ba3a2

17 files changed

+264
-49
lines changed

include/swift/AST/Type.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,6 @@ inline T *staticCastHelper(const Type &Ty) {
611611
template <typename T>
612612
using TypeArrayView = ArrayRefView<Type, T*, staticCastHelper,
613613
/*AllowOrigAccess*/true>;
614-
615614
} // end namespace swift
616615

617616
namespace llvm {

include/swift/Basic/Statistics.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ FRONTEND_STATISTIC(Sema, NumUnloadedLazyIterableDeclContexts)
224224
#include "swift/AST/AccessTypeIDZone.def"
225225
#include "swift/AST/NameLookupTypeIDZone.def"
226226
#include "swift/AST/TypeCheckerTypeIDZone.def"
227+
#include "swift/Sema/IDETypeCheckingRequestIDZone.def"
227228
#include "swift/IDE/IDERequestIDZone.def"
228229
#undef SWIFT_TYPEID
229230

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//===-------- IDETypeCheckingIDZone.def -------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This definition file describes the types in the IDE requests
14+
// TypeID zone, for use with the TypeID template.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
SWIFT_TYPEID(IsDeclApplicableRequest)
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//===----- IDETypeCheckingRequests.h - IDE type-check Requests --*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines IDE type checking request using the evaluator model.
14+
// The file needs to exist in sema because it needs internal implementation
15+
// of the type checker to fulfill some requests
16+
//
17+
//===----------------------------------------------------------------------===//
18+
#ifndef SWIFT_IDE_TYPE_CHECKING_REQUESTS_H
19+
#define SWIFT_IDE_TYPE_CHECKING_REQUESTS_H
20+
21+
#include "swift/AST/ASTTypeIDs.h"
22+
#include "swift/AST/Evaluator.h"
23+
#include "swift/AST/SimpleRequest.h"
24+
#include "swift/AST/TypeCheckRequests.h"
25+
26+
namespace swift {
27+
//----------------------------------------------------------------------------//
28+
// Decl applicability checking
29+
//----------------------------------------------------------------------------//
30+
struct DeclApplicabilityOwner {
31+
const DeclContext *DC;
32+
const Type Ty;
33+
const Decl *ExtensionOrMember;
34+
35+
DeclApplicabilityOwner(const DeclContext *DC, Type Ty, const ExtensionDecl *ED):
36+
DC(DC), Ty(Ty), ExtensionOrMember(ED) {}
37+
DeclApplicabilityOwner(const DeclContext *DC, Type Ty, const ValueDecl *VD):
38+
DC(DC), Ty(Ty), ExtensionOrMember(VD) {}
39+
40+
friend llvm::hash_code hash_value(const DeclApplicabilityOwner &CI) {
41+
return hash_combine(hash_value(CI.Ty.getPointer()),
42+
hash_value(CI.ExtensionOrMember));
43+
}
44+
45+
friend bool operator==(const DeclApplicabilityOwner &lhs,
46+
const DeclApplicabilityOwner &rhs) {
47+
return lhs.Ty.getPointer() == rhs.Ty.getPointer() &&
48+
lhs.ExtensionOrMember == rhs.ExtensionOrMember;
49+
}
50+
51+
friend bool operator!=(const DeclApplicabilityOwner &lhs,
52+
const DeclApplicabilityOwner &rhs) {
53+
return !(lhs == rhs);
54+
}
55+
56+
friend void simple_display(llvm::raw_ostream &out,
57+
const DeclApplicabilityOwner &owner) {
58+
out << "Checking if ";
59+
simple_display(out, owner.ExtensionOrMember);
60+
out << " is applicable for ";
61+
simple_display(out, owner.Ty);
62+
}
63+
};
64+
65+
class IsDeclApplicableRequest:
66+
public SimpleRequest<IsDeclApplicableRequest,
67+
bool(DeclApplicabilityOwner),
68+
CacheKind::Cached> {
69+
public:
70+
using SimpleRequest::SimpleRequest;
71+
72+
private:
73+
friend SimpleRequest;
74+
75+
// Evaluation.
76+
llvm::Expected<bool> evaluate(Evaluator &evaluator,
77+
DeclApplicabilityOwner Owner) const;
78+
79+
public:
80+
// Caching
81+
bool isCached() const { return true; }
82+
// Source location
83+
SourceLoc getNearestLoc() const { return SourceLoc(); };
84+
};
85+
86+
87+
/// The zone number for the IDE.
88+
#define SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE 97
89+
#define SWIFT_TYPEID_ZONE SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE
90+
#define SWIFT_TYPEID_HEADER "swift/Sema/IDETypeCheckingRequestIDZone.def"
91+
#include "swift/Basic/DefineTypeIDZone.h"
92+
#undef SWIFT_TYPEID_ZONE
93+
#undef SWIFT_TYPEID_HEADER
94+
95+
// Set up reporting of evaluated requests.
96+
#define SWIFT_TYPEID(RequestType) \
97+
template<> \
98+
inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \
99+
const RequestType &request) { \
100+
++stats.getFrontendCounters().RequestType; \
101+
}
102+
#include "swift/Sema/IDETypeCheckingRequestIDZone.def"
103+
#undef SWIFT_TYPEID
104+
105+
} // end namespace swift
106+
107+
#endif // SWIFT_IDE_REQUESTS_H

include/swift/Subsystems.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,12 @@ namespace swift {
401401
/// The ASTContext will automatically call these upon construction.
402402
void registerIDERequestFunctions(Evaluator &evaluator);
403403

404+
/// Register type check request functions for IDE's usage with the evaluator.
405+
///
406+
/// The ASTContext will automatically call these upon construction.
407+
/// Calling registerIDERequestFunctions will invoke this function as well.
408+
void registerIDETypeCheckRequestFunctions(Evaluator &evaluator);
409+
404410
} // end namespace swift
405411

406412
#endif // SWIFT_SUBSYSTEMS_H

lib/Frontend/Frontend.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,10 @@ bool CompilerInstance::setUpASTContextIfNeeded() {
189189
Diagnostics));
190190
registerTypeCheckerRequestFunctions(Context->evaluator);
191191

192-
// Migrator and indexing need some IDE requests.
192+
// Migrator, indexing and typo correction need some IDE requests.
193193
if (Invocation.getMigratorOptions().shouldRunMigrator() ||
194-
!Invocation.getFrontendOptions().IndexStorePath.empty()) {
194+
!Invocation.getFrontendOptions().IndexStorePath.empty() ||
195+
Invocation.getLangOptions().TypoCorrectionLimit) {
195196
registerIDERequestFunctions(Context->evaluator);
196197
}
197198
if (setUpModuleLoaders())

lib/IDE/IDERequests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ reinterpret_cast<AbstractRequestFunction *>(&Name::evaluateRequest),
4646
void swift::registerIDERequestFunctions(Evaluator &evaluator) {
4747
evaluator.registerRequestFunctions(SWIFT_IDE_REQUESTS_TYPEID_ZONE,
4848
ideRequestFunctions);
49+
registerIDETypeCheckRequestFunctions(evaluator);
4950
}
5051

5152
//----------------------------------------------------------------------------//

lib/IDE/IDETypeChecking.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/ASTDemangler.h"
2525
#include "swift/AST/ProtocolConformance.h"
2626
#include "swift/Sema/IDETypeChecking.h"
27+
#include "swift/Sema/IDETypeCheckingRequests.h"
2728
#include "swift/IDE/SourceEntityWalker.h"
2829
#include "swift/IDE/IDERequests.h"
2930
#include "swift/Parse/Lexer.h"
@@ -756,3 +757,15 @@ collectAllOverriddenDecls(ValueDecl *VD, bool IncludeProtocolRequirements,
756757
CollectOverriddenDeclsRequest(OverridenDeclsOwner(VD,
757758
IncludeProtocolRequirements, Transitive)), ArrayRef<ValueDecl*>());
758759
}
760+
761+
bool swift::isExtensionApplied(const DeclContext *DC, Type BaseTy,
762+
const ExtensionDecl *ED) {
763+
return evaluateOrDefault(DC->getASTContext().evaluator,
764+
IsDeclApplicableRequest(DeclApplicabilityOwner(DC, BaseTy, ED)), false);
765+
}
766+
767+
bool swift::isMemberDeclApplied(const DeclContext *DC, Type BaseTy,
768+
const ValueDecl *VD) {
769+
return evaluateOrDefault(DC->getASTContext().evaluator,
770+
IsDeclApplicableRequest(DeclApplicabilityOwner(DC, BaseTy, VD)), false);
771+
}

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ add_swift_host_library(swiftSema STATIC
6161
TypeCheckSwitchStmt.cpp
6262
TypeCheckType.cpp
6363
TypeChecker.cpp
64+
IDETypeCheckingRequests.cpp
6465

6566
${EXTRA_TYPECHECKER_FLAGS})
6667
target_link_libraries(swiftSema PRIVATE

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3742,7 +3742,7 @@ void ConstraintSystem::optimizeConstraints(Expr *e) {
37423742
e->walk(optimizer);
37433743
}
37443744

3745-
static bool areGenericRequirementsSatisfied(
3745+
bool swift::areGenericRequirementsSatisfied(
37463746
const DeclContext *DC, const GenericSignature *sig,
37473747
const SubstitutionMap &Substitutions, bool isExtension) {
37483748

@@ -3766,48 +3766,6 @@ static bool areGenericRequirementsSatisfied(
37663766
return CS.solveSingle().hasValue();
37673767
}
37683768

3769-
bool swift::isExtensionApplied(const DeclContext *DC, Type BaseTy,
3770-
const ExtensionDecl *ED) {
3771-
// We can't do anything if the base type has unbound generic parameters.
3772-
// We can't leak type variables into another constraint system.
3773-
if (BaseTy->hasTypeVariable() || BaseTy->hasUnboundGenericType() ||
3774-
BaseTy->hasUnresolvedType() || BaseTy->hasError())
3775-
return true;
3776-
3777-
if (!ED->isConstrainedExtension())
3778-
return true;
3779-
3780-
TypeChecker *TC = &createTypeChecker(DC->getASTContext());
3781-
TC->validateExtension(const_cast<ExtensionDecl *>(ED));
3782-
3783-
GenericSignature *genericSig = ED->getGenericSignature();
3784-
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap(
3785-
DC->getParentModule(), ED->getExtendedNominal());
3786-
return areGenericRequirementsSatisfied(DC, genericSig, substMap,
3787-
/*isExtension=*/true);
3788-
}
3789-
3790-
bool swift::isMemberDeclApplied(const DeclContext *DC, Type BaseTy,
3791-
const ValueDecl *VD) {
3792-
// We can't leak type variables into another constraint system.
3793-
// We can't do anything if the base type has unbound generic parameters.
3794-
if (BaseTy->hasTypeVariable() || BaseTy->hasUnboundGenericType()||
3795-
BaseTy->hasUnresolvedType() || BaseTy->hasError())
3796-
return true;
3797-
3798-
const GenericContext *genericDecl = VD->getAsGenericContext();
3799-
if (!genericDecl)
3800-
return true;
3801-
const GenericSignature *genericSig = genericDecl->getGenericSignature();
3802-
if (!genericSig)
3803-
return true;
3804-
3805-
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap(
3806-
DC->getParentModule(), VD->getDeclContext());
3807-
return areGenericRequirementsSatisfied(DC, genericSig, substMap,
3808-
/*isExtension=*/false);
3809-
}
3810-
38113769
static bool canSatisfy(Type type1, Type type2, bool openArchetypes,
38123770
ConstraintKind kind, DeclContext *dc) {
38133771
std::unique_ptr<TypeChecker> CreatedTC;

lib/Sema/IDETypeCheckingRequests.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/AST/ASTPrinter.h"
14+
#include "swift/AST/Decl.h"
15+
#include "swift/AST/NameLookup.h"
16+
#include "swift/Basic/SourceManager.h"
17+
#include "swift/Frontend/Frontend.h"
18+
#include "swift/Sema/IDETypeCheckingRequests.h"
19+
#include "swift/Subsystems.h"
20+
#include "TypeChecker.h"
21+
22+
using namespace swift;
23+
24+
namespace swift {
25+
// Implement the IDE type zone.
26+
#define SWIFT_TYPEID_ZONE SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE
27+
#define SWIFT_TYPEID_HEADER "swift/Sema/IDETypeCheckingRequestIDZone.def"
28+
#include "swift/Basic/ImplementTypeIDZone.h"
29+
#undef SWIFT_TYPEID_ZONE
30+
#undef SWIFT_TYPEID_HEADER
31+
}
32+
33+
// Define request evaluation functions for each of the IDE type check requests.
34+
static AbstractRequestFunction *ideTypeCheckRequestFunctions[] = {
35+
#define SWIFT_TYPEID(Name) \
36+
reinterpret_cast<AbstractRequestFunction *>(&Name::evaluateRequest),
37+
#include "swift/Sema/IDETypeCheckingRequestIDZone.def"
38+
#undef SWIFT_TYPEID
39+
};
40+
41+
void swift::registerIDETypeCheckRequestFunctions(Evaluator &evaluator) {
42+
evaluator.registerRequestFunctions(SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE,
43+
ideTypeCheckRequestFunctions);
44+
}
45+
46+
static bool isExtensionAppliedInternal(const DeclContext *DC, Type BaseTy,
47+
const ExtensionDecl *ED) {
48+
// We can't do anything if the base type has unbound generic parameters.
49+
// We can't leak type variables into another constraint system.
50+
if (BaseTy->hasTypeVariable() || BaseTy->hasUnboundGenericType() ||
51+
BaseTy->hasUnresolvedType() || BaseTy->hasError())
52+
return true;
53+
54+
if (!ED->isConstrainedExtension())
55+
return true;
56+
57+
TypeChecker *TC = &TypeChecker::createForContext((DC->getASTContext()));
58+
TC->validateExtension(const_cast<ExtensionDecl *>(ED));
59+
60+
GenericSignature *genericSig = ED->getGenericSignature();
61+
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap(
62+
DC->getParentModule(), ED->getExtendedNominal());
63+
return areGenericRequirementsSatisfied(DC, genericSig, substMap,
64+
/*isExtension=*/true);
65+
}
66+
67+
static bool isMemberDeclAppliedInternal(const DeclContext *DC, Type BaseTy,
68+
const ValueDecl *VD) {
69+
// We can't leak type variables into another constraint system.
70+
// We can't do anything if the base type has unbound generic parameters.
71+
if (BaseTy->hasTypeVariable() || BaseTy->hasUnboundGenericType()||
72+
BaseTy->hasUnresolvedType() || BaseTy->hasError())
73+
return true;
74+
75+
const GenericContext *genericDecl = VD->getAsGenericContext();
76+
if (!genericDecl)
77+
return true;
78+
const GenericSignature *genericSig = genericDecl->getGenericSignature();
79+
if (!genericSig)
80+
return true;
81+
82+
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap(
83+
DC->getParentModule(), VD->getDeclContext());
84+
return areGenericRequirementsSatisfied(DC, genericSig, substMap,
85+
/*isExtension=*/false);
86+
}
87+
88+
llvm::Expected<bool>
89+
IsDeclApplicableRequest::evaluate(Evaluator &evaluator,
90+
DeclApplicabilityOwner Owner) const {
91+
if (auto *VD = dyn_cast<ValueDecl>(Owner.ExtensionOrMember)) {
92+
return isMemberDeclAppliedInternal(Owner.DC, Owner.Ty, VD);
93+
} else if (auto *ED = dyn_cast<ExtensionDecl>(Owner.ExtensionOrMember)) {
94+
return isExtensionAppliedInternal(Owner.DC, Owner.Ty, ED);
95+
} else {
96+
llvm_unreachable("unhandled decl kind");
97+
}
98+
}

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/ProtocolConformance.h"
2525
#include "swift/Basic/SourceManager.h"
2626
#include "swift/Basic/STLExtras.h"
27+
#include "swift/Sema/IDETypeCheckingRequests.h"
2728
#include "swift/Sema/IDETypeChecking.h"
2829
#include "llvm/ADT/SetVector.h"
2930
#include <set>
@@ -197,7 +198,9 @@ static void collectVisibleMemberDecls(const DeclContext *CurrDC, LookupState LS,
197198
continue;
198199
if (!isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver))
199200
continue;
200-
if (!isMemberDeclApplied(CurrDC, BaseType, VD))
201+
if (!evaluateOrDefault(CurrDC->getASTContext().evaluator,
202+
IsDeclApplicableRequest(DeclApplicabilityOwner(CurrDC, BaseType, VD)),
203+
false))
201204
continue;
202205
FoundDecls.push_back(VD);
203206
}
@@ -216,8 +219,9 @@ static void doGlobalExtensionLookup(Type BaseType,
216219

217220
// Look in each extension of this type.
218221
for (auto extension : nominal->getExtensions()) {
219-
if (!isExtensionApplied(const_cast<DeclContext *>(CurrDC), BaseType,
220-
extension))
222+
if (!evaluateOrDefault(CurrDC->getASTContext().evaluator,
223+
IsDeclApplicableRequest(DeclApplicabilityOwner(CurrDC, BaseType,
224+
extension)), false))
221225
continue;
222226

223227
collectVisibleMemberDecls(CurrDC, LS, BaseType, extension, FoundDecls,

0 commit comments

Comments
 (0)