14
14
// to define new request kinds.
15
15
//
16
16
// ===----------------------------------------------------------------------===//
17
- #ifndef SWIFT_BASIC_SIMPLEREQUEST_H
18
- #define SWIFT_BASIC_SIMPLEREQUEST_H
17
+ #ifndef SWIFT_AST_SIMPLEREQUEST_H
18
+ #define SWIFT_AST_SIMPLEREQUEST_H
19
19
20
+ #include " swift/AST/DiagnosticEngine.h"
21
+ #include " swift/AST/DiagnosticsCommon.h"
20
22
#include " swift/Basic/SimpleDisplay.h"
21
23
#include " swift/Basic/TypeID.h"
22
24
#include " llvm/ADT/Hashing.h"
@@ -30,6 +32,41 @@ class Evaluator;
30
32
// / CRTP base class that describes a request operation that takes values
31
33
// / with the given input types (\c Inputs...) and produces an output of
32
34
// / the given type.
35
+ // /
36
+ // / \tparam Derived The final, derived class type for the request.
37
+ // / \tparam Output The type of the result produced by evaluating this request.
38
+ // / \tparam Inputs The types of the inputs to this request, i.e., the values
39
+ // / that comprise the request itself. These will determine the uniqueness of
40
+ // / the request.
41
+ // /
42
+ // / The Derived class needs to implement several operations. The most important
43
+ // / one takes an evaluator and the input values, then computes the final
44
+ // / result:
45
+ // / \code
46
+ // / Output operator()(Evaluator &evaluator, Inputs...) const;
47
+ // / \endcode
48
+ // /
49
+ // / The Derived class will also need to implement an operation to break a
50
+ // / cycle if one is found, i.e.,
51
+ // / \code
52
+ // / OutputType breakCycle() const;
53
+ // / \endcode
54
+ // /
55
+ // / Cycle diagnostics can be handled in one of two ways. Either the Derived
56
+ // / class can implement the two cycle-diagnosing operations directly:
57
+ // / \code
58
+ // / void diagnoseCycle(DiagnosticEngine &diags) const;
59
+ // / void noteCycleStep(DiagnosticEngine &diags) const;
60
+ // / \endcode
61
+ // /
62
+ // / Or the Derived class can provide a "diagnostic location" operation and
63
+ // / diagnostic values for the main cycle diagnostic and a "note" describing a
64
+ // / step within the chain of diagnostics:
65
+ // / \code
66
+ // / T getCycleDiagnosticLoc(Inputs...) const;
67
+ // / static constexpr Diag<Inputs...> cycleDiagnostic = ...;
68
+ // / static constexpr Diag<Inputs...> cycleStepDiagnostic = ...;
69
+ // / \endcode
33
70
template <typename Derived, typename Output, typename ...Inputs>
34
71
class SimpleRequest {
35
72
std::tuple<Inputs...> storage;
@@ -49,6 +86,14 @@ class SimpleRequest {
49
86
return asDerived ()(evaluator, std::get<Indices>(storage)...);
50
87
}
51
88
89
+ template <size_t ...Indices>
90
+ void diagnoseImpl (DiagnosticEngine &diags, Diag<Inputs...> diag,
91
+ llvm::index_sequence<Indices...>) const {
92
+ diags.diagnose (
93
+ asDerived ().getCycleDiagnosticLoc (std::get<Indices>(storage)...),
94
+ diag, std::get<Indices>(storage)...);
95
+ }
96
+
52
97
protected:
53
98
// / Retrieve the storage value directly.
54
99
const std::tuple<Inputs...> &getStorage () const { return storage; }
@@ -62,7 +107,17 @@ class SimpleRequest {
62
107
OutputType operator ()(Evaluator &evaluator) const {
63
108
return callDerived (evaluator, llvm::index_sequence_for<Inputs...>());
64
109
}
65
-
110
+
111
+ void diagnoseCycle (DiagnosticEngine &diags) const {
112
+ diagnoseImpl (diags, Derived::cycleDiagnostic,
113
+ llvm::index_sequence_for<Inputs...>());
114
+ }
115
+
116
+ void noteCycleStep (DiagnosticEngine &diags) const {
117
+ diagnoseImpl (diags, Derived::cycleStepDiagnostic,
118
+ llvm::index_sequence_for<Inputs...>());
119
+ }
120
+
66
121
friend bool operator ==(const SimpleRequest &lhs, const SimpleRequest &rhs) {
67
122
return lhs.storage == rhs.storage ;
68
123
}
0 commit comments