Skip to content

Commit 2e61629

Browse files
committed
🎨 Improve flow error messages
Problem: - Flow errors use a hacky technique to output useful information. Solution: - Use `stdx::ct_check`.
1 parent f68cd9c commit 2e61629

File tree

5 files changed

+50
-82
lines changed

5 files changed

+50
-82
lines changed

.github/workflows/asciidoctor-ghpages.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
- name: Checkout source
3636
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
3737
- name: Setup Node.js
38-
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
38+
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
3939
with:
4040
node-version: 20
4141
- name: Install Mermaid

include/flow/graph_builder.hpp

Lines changed: 44 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -52,28 +52,6 @@ template <typename T> using name_for = typename T::name_t;
5252
});
5353
}
5454

55-
template <typename Cond> struct sequence_conditions;
56-
57-
template <auto...> struct INFO_flow_name_;
58-
59-
template <auto...> struct INFO_step_a_name_;
60-
61-
template <auto...> struct INFO_step_a_condition_;
62-
63-
template <auto...> struct INFO_step_b_name_;
64-
65-
template <auto...> struct INFO_step_b_condition_;
66-
67-
template <auto...> struct INFO_sequence_condition_;
68-
69-
template <typename...> struct INFO_sequence_missing_predicate_;
70-
71-
template <typename...> constexpr bool ERROR_DETAILS_ = false;
72-
73-
template <auto...> struct INFO_missing_steps_;
74-
75-
template <auto...> struct INFO_duplicated_steps_;
76-
7755
template <stdx::ct_string Name,
7856
template <stdx::ct_string, std::size_t> typename Impl>
7957
struct graph_builder {
@@ -101,29 +79,20 @@ struct graph_builder {
10179
stdx::for_each(
10280
[&]<typename P>(P const &) {
10381
if constexpr (not stdx::contains_type<edge_ps_t, P>) {
104-
static_assert(
105-
ERROR_DETAILS_<
106-
INFO_flow_name_<Name>,
107-
INFO_step_a_name_<lhs_t::ct_name>,
108-
INFO_step_a_condition_<
109-
lhs_t::condition.ct_name>,
110-
INFO_step_b_name_<rhs_t::ct_name>,
111-
INFO_step_b_condition_<
112-
rhs_t::condition.ct_name>,
113-
INFO_sequence_condition_<Cond::ct_name>,
114-
INFO_sequence_missing_predicate_<P>>,
115-
116-
"The conditions on this sequence "
117-
"(step_a >> step_b) are weaker than those on "
118-
"step_a and/or step_b. The sequence could be "
119-
"enabled while step_a and/or step_b is not. "
120-
"Specifically, the sequence is missing the "
121-
"predicate identified in "
122-
"`INFO_sequence_missing_predicate_`. TIP: "
123-
"Look for 'ERROR_DETAILS_` and `INFO_` in "
124-
"the compiler error message for details on "
125-
"the sequence, the step names, and the "
126-
"conditions.");
82+
constexpr auto error = stdx::ct_format<
83+
"The conditions on the sequence ({} >> "
84+
"{})[{}] are weaker than those on {}[{}] or "
85+
"{}[{}]. Specifically, the sequence is missing "
86+
"the predicate: {}">(
87+
CX_VALUE(lhs_t::ct_name),
88+
CX_VALUE(rhs_t::ct_name),
89+
CX_VALUE(Cond::ct_name),
90+
CX_VALUE(lhs_t::ct_name),
91+
CX_VALUE(lhs_t::condition.ct_name),
92+
CX_VALUE(rhs_t::ct_name),
93+
CX_VALUE(rhs_t::condition.ct_name),
94+
CX_VALUE(P));
95+
stdx::ct_check<false>.template emit<error>();
12796
}
12897
},
12998
node_ps);
@@ -208,44 +177,43 @@ struct graph_builder {
208177
boost::mp11::mp_set_difference<mentioned_node_names_t,
209178
node_names_t>;
210179

211-
constexpr auto missing_nodes = missing_nodes_t{};
212-
constexpr auto missing_nodes_ct_strings = stdx::transform(
213-
[]<typename N>(N) { return stdx::ct_string_from_type(N{}); },
214-
missing_nodes);
215-
216-
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
217-
using error_details_t = INFO_missing_steps_<stdx::get<Is>(
218-
missing_nodes_ct_strings)...>;
219-
220-
static_assert(
221-
ERROR_DETAILS_<INFO_flow_name_<Name>, error_details_t>,
222-
"One or more steps are referenced in the flow but not "
223-
"explicitly added with the * operator. The "
224-
"beginning of this error shows you which steps are "
225-
"missing.");
226-
}(std::make_index_sequence<
227-
stdx::tuple_size_v<decltype(missing_nodes)>>{});
180+
constexpr auto error =
181+
stdx::ct_format<"One or more steps are referenced in the "
182+
"flow ({}) but not explicitly added with the "
183+
"* operator. The missing steps are: {}.">(
184+
CX_VALUE(Name),
185+
CX_VALUE(stdx::transform(
186+
[]<typename N>(N) {
187+
return stdx::ct_string_from_type(N{});
188+
},
189+
missing_nodes_t{})
190+
.join([](auto x, auto y) {
191+
using namespace stdx::literals;
192+
return x + ", "_cts + y;
193+
})));
194+
stdx::ct_check<false>.template emit<error>();
228195
}
229196

230197
if constexpr (stdx::tuple_size_v<node_names_t> !=
231198
stdx::tuple_size_v<decltype(node_names)>) {
232199
constexpr auto duplicates = stdx::transform(
233-
[](auto e) {
234-
return stdx::ct_string_from_type(stdx::get<0>(e));
235-
},
200+
[](auto e) { return stdx::get<0>(e); },
236201
stdx::filter<detail::is_duplicated>(stdx::gather(node_names)));
237202

238-
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
239-
using error_details_t =
240-
INFO_duplicated_steps_<stdx::get<Is>(duplicates)...>;
241-
242-
static_assert(
243-
ERROR_DETAILS_<INFO_flow_name_<Name>, error_details_t>,
244-
"One or more steps are explicitly added more than once "
245-
"using the * operator. The beginning of this "
246-
"error shows you which steps are duplicated.");
247-
}(std::make_index_sequence<
248-
stdx::tuple_size_v<decltype(duplicates)>>{});
203+
constexpr auto error = stdx::ct_format<
204+
"One or more steps in the flow ({}) are explicitly added more "
205+
"than once using the * operator. The duplicate steps are: {}.">(
206+
CX_VALUE(Name),
207+
CX_VALUE(stdx::transform(
208+
[]<typename N>(N) {
209+
return stdx::ct_string_from_type(N{});
210+
},
211+
decltype(duplicates){})
212+
.join([](auto x, auto y) {
213+
using namespace stdx::literals;
214+
return x + ", "_cts + y;
215+
})));
216+
stdx::ct_check<false>.template emit<error>();
249217
}
250218
}
251219

test/flow/fail/mismatched_flow_runtime_conditional.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include <cib/cib.hpp>
22
#include <flow/flow.hpp>
33

4-
// EXPECT: The conditions on this sequence
4+
// EXPECT: The conditions on the sequence
55

66
namespace {
77
using namespace flow::literals;

test/flow/fail/node_explicitly_added_twice.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
#include <cib/cib.hpp>
22
#include <flow/flow.hpp>
33

4-
// EXPECT: One or more steps are explicitly added more than once
4+
// EXPECT: are explicitly added more than once
55

66
namespace {
77
using namespace flow::literals;
88

99
constexpr auto a = flow::milestone<"a">();
1010

11-
struct TestFlowAlpha : public flow::service<> {};
11+
struct TestFlowAlpha : public flow::service<"alpha"> {};
1212

1313
struct FlowConfig {
1414
constexpr static auto config = cib::config(

test/flow/fail/only_reference_added.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
#include <cib/cib.hpp>
22
#include <flow/flow.hpp>
33

4-
// EXPECT: One or more steps are referenced in the flow but not explicitly
4+
// EXPECT: One or more steps are referenced in the flow
55

66
namespace {
77
using namespace flow::literals;
88

99
constexpr auto a = flow::milestone<"a">();
1010

11-
struct TestFlowAlpha : public flow::service<> {};
11+
struct TestFlowAlpha : public flow::service<"alpha"> {};
1212

1313
struct FlowConfig {
1414
constexpr static auto config =

0 commit comments

Comments
 (0)