Skip to content

Commit 1a8a70e

Browse files
authored
Merge pull request #17643 from DougGregor/evaluator-indirect-evaluation
[Evaluator] Separate formation of a request from evaluation of that request
2 parents b1c79fc + 5c6c236 commit 1a8a70e

22 files changed

+322
-268
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,24 @@ ERROR(attr_only_on_parameters, none,
9393
ERROR(function_type_no_parens,none,
9494
"single argument function types require parentheses", ())
9595

96+
//------------------------------------------------------------------------------
97+
// MARK: Circular reference diagnostics
98+
//------------------------------------------------------------------------------
99+
ERROR(circular_reference, none,
100+
"circular reference", ())
101+
102+
ERROR(redundant_type_alias_define, none,
103+
"redundant type alias declaration", ())
104+
105+
NOTE(circular_reference_through, none,
106+
"through reference here", ())
107+
108+
ERROR(circular_class_inheritance,none,
109+
"%0 inherits from itself", (Identifier))
110+
111+
ERROR(circular_enum_inheritance,none,
112+
"%0 has a raw type that depends on itself", (Identifier))
113+
96114
#ifndef DIAG_NO_UNDEF
97115
# if defined(DIAG)
98116
# undef DIAG

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,8 +2155,6 @@ ERROR(superclass_not_open,none,
21552155
NOTE(superclass_here,none,"superclass is declared here", ())
21562156
ERROR(superclass_of_open_not_open,none,
21572157
"superclass %0 of open class must be open", (Type))
2158-
ERROR(circular_class_inheritance,none,
2159-
"%0 inherits from itself", (Identifier))
21602158
ERROR(inheritance_from_final_class,none,
21612159
"inheritance from a final class %0", (Identifier))
21622160
ERROR(inheritance_from_unspecialized_objc_generic_class,none,
@@ -2199,8 +2197,6 @@ ERROR(enum_stored_property,none,
21992197
// Enum raw types
22002198
ERROR(multiple_enum_raw_types,none,
22012199
"multiple enum raw types %0 and %1", (Type, Type))
2202-
ERROR(circular_enum_inheritance,none,
2203-
"%0 has a raw type that depends on itself", (Identifier))
22042200
ERROR(raw_type_not_first,none,
22052201
"raw type %0 must appear first in the enum inheritance clause", (Type))
22062202
ERROR(raw_type_not_literal_convertible,none,
@@ -4061,18 +4057,6 @@ WARNING(variable_never_read, none,
40614057
"%select{variable|parameter}1 %0 was written to, but never read",
40624058
(Identifier, unsigned))
40634059

4064-
//------------------------------------------------------------------------------
4065-
// MARK: Circular reference diagnostics
4066-
//------------------------------------------------------------------------------
4067-
ERROR(circular_reference, none,
4068-
"circular reference", ())
4069-
4070-
ERROR(redundant_type_alias_define, none,
4071-
"redundant type alias declaration", ())
4072-
4073-
NOTE(circular_reference_through, none,
4074-
"through reference here", ())
4075-
40764060
//------------------------------------------------------------------------------
40774061
// MARK: Debug diagnostics
40784062
//------------------------------------------------------------------------------

include/swift/AST/Evaluator.h

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,23 @@ class raw_ostream;
3737

3838
namespace swift {
3939

40+
using llvm::ArrayRef;
4041
using llvm::Optional;
4142
using llvm::None;
4243

4344
class DiagnosticEngine;
45+
class Evaluator;
4446
class UnifiedStatsReporter;
4547

48+
/// An "abstract" request function pointer, which is the storage type
49+
/// used for each of the
50+
using AbstractRequestFunction = void(void);
51+
52+
/// Form the specific request function for the given request type.
53+
template<typename Request>
54+
using RequestFunction =
55+
typename Request::OutputType(const Request &, Evaluator &);
56+
4657
/// Pretty stack trace handler for an arbitrary request.
4758
template<typename Request>
4859
class PrettyStackTraceRequest : public llvm::PrettyStackTraceEntry {
@@ -59,7 +70,7 @@ class PrettyStackTraceRequest : public llvm::PrettyStackTraceEntry {
5970
};
6071

6172
/// Report that a request of the given kind is being evaluated, so it
62-
/// can be recoded by the stats reporter.
73+
/// can be recorded by the stats reporter.
6374
template<typename Request>
6475
void reportEvaluatedRequest(UnifiedStatsReporter &stats,
6576
const Request &request) { }
@@ -138,6 +149,18 @@ class Evaluator {
138149
/// non-null.
139150
UnifiedStatsReporter *stats = nullptr;
140151

152+
/// A vector containing the abstract request functions that can compute
153+
/// the result of a particular request within a given zone. The
154+
/// \c uint8_t is the zone number of the request, and the array is
155+
/// indexed by the index of the request type within that zone. Each
156+
/// entry is a function pointer that will be reinterpret_cast'd to
157+
///
158+
/// RequestType::OutputType (*)(const RequestType &request,
159+
/// Evaluator &evaluator);
160+
/// and called to satisfy the request.
161+
std::vector<std::pair<uint8_t, ArrayRef<AbstractRequestFunction *>>>
162+
requestFunctionsByZone;
163+
141164
/// A vector containing all of the active evaluation requests, which
142165
/// is treated as a stack and is used to detect cycles.
143166
llvm::SetVector<AnyRequest> activeRequests;
@@ -156,6 +179,19 @@ class Evaluator {
156179
/// so all clients must cope with cycles.
157180
llvm::DenseMap<AnyRequest, std::vector<AnyRequest>> dependencies;
158181

182+
/// Retrieve the request function for the given zone and request IDs.
183+
AbstractRequestFunction *getAbstractRequestFunction(uint8_t zoneID,
184+
uint8_t requestID) const;
185+
186+
/// Retrieve the request function for the given request type.
187+
template<typename Request>
188+
auto getRequestFunction() const -> RequestFunction<Request> * {
189+
auto abstractFn = getAbstractRequestFunction(TypeID<Request>::zoneID,
190+
TypeID<Request>::localID);
191+
assert(abstractFn && "No request function for request");
192+
return reinterpret_cast<RequestFunction<Request> *>(abstractFn);
193+
}
194+
159195
public:
160196
/// Construct a new evaluator that can emit cyclic-dependency
161197
/// diagnostics through the given diagnostics engine.
@@ -165,6 +201,13 @@ class Evaluator {
165201
/// statistics will be recorded.
166202
void setStatsReporter(UnifiedStatsReporter *stats) { this->stats = stats; }
167203

204+
/// Register the set of request functions for the given zone.
205+
///
206+
/// These functions will be called to evaluate any requests within that
207+
/// zone.
208+
void registerRequestFunctions(uint8_t zoneID,
209+
ArrayRef<AbstractRequestFunction *> functions);
210+
168211
/// Evaluate the given request and produce its result,
169212
/// consulting/populating the cache as required.
170213
template<typename Request>
@@ -247,7 +290,7 @@ class Evaluator {
247290
/// Update statistics.
248291
if (stats) reportEvaluatedRequest(*stats, request);
249292

250-
return request(*this);
293+
return getRequestFunction<Request>()(request, *this);
251294
}
252295

253296
/// Get the result of a request, consulting an external cache
@@ -260,17 +303,8 @@ class Evaluator {
260303
if (auto cached = request.getCachedResult())
261304
return *cached;
262305

263-
// Clear out the dependencies on this request; we're going to recompute
264-
// them now anyway.
265-
dependencies[request].clear();
266-
267-
PrettyStackTraceRequest<Request> prettyStackTrace(request);
268-
269-
/// Update statistics.
270-
if (stats) reportEvaluatedRequest(*stats, request);
271-
272-
// Service the request.
273-
auto result = request(*this);
306+
// Compute the result.
307+
auto result = getResultUncached(request);
274308

275309
// Cache the result.
276310
request.cacheResult(result);
@@ -293,12 +327,8 @@ class Evaluator {
293327
return known->second.castTo<typename Request::OutputType>();
294328
}
295329

296-
// Clear out the dependencies on this request; we're going to recompute
297-
// them now anyway.
298-
dependencies[request].clear();
299-
300-
// Evaluate the request.
301-
auto result = request(*this);
330+
// Compute the result.
331+
auto result = getResultUncached(request);
302332

303333
// Cache the result.
304334
cache.insert({anyRequest, result});
@@ -314,7 +344,7 @@ class Evaluator {
314344
llvm::raw_ostream &out,
315345
llvm::DenseSet<AnyRequest> &visitedAnywhere,
316346
llvm::SmallVectorImpl<AnyRequest> &visitedAlongPath,
317-
llvm::ArrayRef<AnyRequest> highlightPath,
347+
ArrayRef<AnyRequest> highlightPath,
318348
std::string &prefixStr,
319349
bool lastChild) const;
320350

include/swift/AST/LazyResolver.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,6 @@ class LazyResolver {
7171
/// Resolve the "is Objective-C" bit for the given declaration.
7272
virtual void resolveIsObjC(ValueDecl *VD) = 0;
7373

74-
/// Retrieve the superclass of the given class.
75-
virtual Type getSuperclass(const ClassDecl *classDecl) = 0;
76-
77-
/// Retrieve the superclass of the given protocol.
78-
virtual Type getSuperclass(const ProtocolDecl *protocolDecl) = 0;
79-
80-
/// Resolve the raw type of the given enum.
81-
virtual Type getRawType(EnumDecl *enumDecl) = 0;
82-
83-
/// Get a specific inherited type from the given declaration.
84-
virtual Type getInheritedType(
85-
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
86-
unsigned index) = 0;
87-
8874
/// Resolve the trailing where clause of the given protocol in-place.
8975
virtual void resolveTrailingWhereClause(ProtocolDecl *proto) = 0;
9076

include/swift/AST/SimpleRequest.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ enum class CacheKind {
5656
/// important one takes an evaluator and the input values, then computes the
5757
/// final result:
5858
/// \code
59-
/// Output operator()(Evaluator &evaluator, Inputs...) const;
59+
/// Output evaluate(Evaluator &evaluator, Inputs...) const;
6060
/// \endcode
6161
///
6262
/// The \c Derived class will also need to implement an operation to break a
@@ -105,8 +105,8 @@ class SimpleRequest {
105105
template<size_t ...Indices>
106106
Output callDerived(Evaluator &evaluator,
107107
llvm::index_sequence<Indices...>) const {
108-
static_assert(sizeof...(Indices) > 0, "Subclass must define operator()");
109-
return asDerived()(evaluator, std::get<Indices>(storage)...);
108+
static_assert(sizeof...(Indices) > 0, "Subclass must define evaluate()");
109+
return asDerived().evaluate(evaluator, std::get<Indices>(storage)...);
110110
}
111111

112112
template<size_t ...Indices>
@@ -130,8 +130,11 @@ class SimpleRequest {
130130
explicit SimpleRequest(const Inputs& ...inputs)
131131
: storage(inputs...) { }
132132

133-
OutputType operator()(Evaluator &evaluator) const {
134-
return callDerived(evaluator, llvm::index_sequence_for<Inputs...>());
133+
/// Request evaluation function that will be registered with the evaluator.
134+
static OutputType evaluateRequest(const Derived &request,
135+
Evaluator &evaluator) {
136+
return request.callDerived(evaluator,
137+
llvm::index_sequence_for<Inputs...>());
135138
}
136139

137140
void diagnoseCycle(DiagnosticEngine &diags) const {

include/swift/Sema/TypeCheckRequests.h renamed to include/swift/AST/TypeCheckRequests.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,14 @@ class InheritedTypeRequest :
4646

4747
public:
4848
using SimpleRequest::SimpleRequest;
49-
using SimpleRequest::operator();
5049

5150
private:
5251
friend class SimpleRequest;
5352

5453
// Evaluation.
55-
Type operator()(Evaluator &evaluator,
56-
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
57-
unsigned index) const;
54+
Type evaluate(Evaluator &evaluator,
55+
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
56+
unsigned index) const;
5857

5958
public:
6059
// Cycle handling
@@ -76,13 +75,12 @@ class SuperclassTypeRequest :
7675
NominalTypeDecl *> {
7776
public:
7877
using SimpleRequest::SimpleRequest;
79-
using SimpleRequest::operator();
8078

8179
private:
8280
friend class SimpleRequest;
8381

8482
// Evaluation.
85-
Type operator()(Evaluator &evaluator, NominalTypeDecl *classDecl) const;
83+
Type evaluate(Evaluator &evaluator, NominalTypeDecl *classDecl) const;
8684

8785
public:
8886
// Cycle handling
@@ -104,13 +102,12 @@ class EnumRawTypeRequest :
104102
EnumDecl *> {
105103
public:
106104
using SimpleRequest::SimpleRequest;
107-
using SimpleRequest::operator();
108105

109106
private:
110107
friend class SimpleRequest;
111108

112109
// Evaluation.
113-
Type operator()(Evaluator &evaluator, EnumDecl *enumDecl) const;
110+
Type evaluate(Evaluator &evaluator, EnumDecl *enumDecl) const;
114111

115112
public:
116113
// Cycle handling
@@ -124,8 +121,11 @@ class EnumRawTypeRequest :
124121
void cacheResult(Type value) const;
125122
};
126123

127-
#define SWIFT_TYPEID_ZONE 10
128-
#define SWIFT_TYPEID_HEADER "swift/Sema/TypeCheckerTypeIDZone.def"
124+
/// The zone number for the type checker.
125+
#define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10
126+
127+
#define SWIFT_TYPEID_ZONE SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE
128+
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
129129
#include "swift/Basic/DefineTypeIDZone.h"
130130

131131
// Set up reporting of evaluated requests.
@@ -135,7 +135,7 @@ inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \
135135
const RequestType &request) { \
136136
++stats.getFrontendCounters().RequestType; \
137137
}
138-
#include "swift/Sema/TypeCheckerTypeIDZone.def"
138+
#include "swift/AST/TypeCheckerTypeIDZone.def"
139139
#undef SWIFT_TYPEID
140140

141141
} // end namespace swift

include/swift/Sema/TypeCheckerTypeIDZone.def renamed to include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- ArithmeticEvaluatorTypeIDZone.def - --------------------*- C++ -*-===//
1+
//===--- TypeCheckerTypeIDZone.def ------------------------------*- C++ -*-===//
22
//
33
// This source file is part of the Swift.org open source project
44
//

include/swift/Basic/DefineTypeIDZone.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,15 @@ template<> struct TypeIDZoneTypes<SWIFT_TYPEID_ZONE> {
4646
};
4747

4848
// Second pass: create specializations of TypeID for these types.
49-
#define SWIFT_TYPEID_NAMED(Type, Name) \
50-
template<> struct TypeID<Type> { \
51-
static const uint64_t value = \
52-
formTypeID(SWIFT_TYPEID_ZONE, \
53-
TypeIDZoneTypes<SWIFT_TYPEID_ZONE>::Name); \
54-
\
55-
static llvm::StringRef getName() { \
56-
return #Name; \
57-
} \
49+
#define SWIFT_TYPEID_NAMED(Type, Name) \
50+
template<> struct TypeID<Type> { \
51+
static const uint8_t zoneID = SWIFT_TYPEID_ZONE; \
52+
static const uint8_t localID = \
53+
TypeIDZoneTypes<SWIFT_TYPEID_ZONE>::Name; \
54+
\
55+
static const uint64_t value = formTypeID(zoneID, localID); \
56+
\
57+
static llvm::StringRef getName() { return #Name; } \
5858
};
5959

6060
#define SWIFT_TYPEID_TEMPLATE1_NAMED(Template, Name, Param1, Arg1) \

include/swift/Basic/Statistics.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ FRONTEND_STATISTIC(Sema, NumUnloadedLazyIterableDeclContexts)
197197

198198
/// All type check requests go into the Sema area.
199199
#define SWIFT_TYPEID(NAME) FRONTEND_STATISTIC(Sema, NAME)
200-
#include "swift/Sema/TypeCheckerTypeIDZone.def"
200+
#include "swift/AST/TypeCheckerTypeIDZone.def"
201201
#undef SWIFT_TYPEID
202202

203203
/// The next 10 statistics count 5 kinds of SIL entities present

include/swift/Subsystems.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ namespace swift {
4646
class DelayedParsingCallbacks;
4747
class DiagnosticConsumer;
4848
class DiagnosticEngine;
49+
class Evaluator;
4950
class FileUnit;
5051
class GenericEnvironment;
5152
class GenericParamList;
@@ -342,6 +343,13 @@ namespace swift {
342343
struct Implementation;
343344
Implementation &Impl;
344345
};
346+
347+
/// Register the type checker's request functions with the evaluator.
348+
///
349+
/// Clients that form an ASTContext and will perform any semantic
350+
/// queries should call this function after forming the ASTContext.
351+
void registerTypeCheckerRequestFunctions(Evaluator &evaluator);
352+
345353
} // end namespace swift
346354

347355
#endif // SWIFT_SUBSYSTEMS_H

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ add_swift_library(swiftAST STATIC
5252
SubstitutionMap.cpp
5353
SwiftNameTranslation.cpp
5454
Type.cpp
55+
TypeCheckRequests.cpp
5556
TypeJoinMeet.cpp
5657
TypeRefinementContext.cpp
5758
TypeRepr.cpp

0 commit comments

Comments
 (0)