Skip to content

reduce use of SFINAE to shorten error messages#44

Merged
oliverlee merged 1 commit intomainfrom
Ibc7ab9d85dc732ae7b895093147584211ef713ac
Jun 17, 2025
Merged

reduce use of SFINAE to shorten error messages#44
oliverlee merged 1 commit intomainfrom
Ibc7ab9d85dc732ae7b895093147584211ef713ac

Conversation

@oliverlee
Copy link
Owner

@oliverlee oliverlee commented Jun 17, 2025

Remove SFINAE from user-facing functions to reduce the length of compiler
errors. For example, the error for eq(a == b) instead of eq(a, b) is

before
external/toolchains_llvm++llvm+llvm_toolchain_llvm/bin/../include/c++/v1/__type_traits/invoke.h:314:1: error: no type named 'type' in 'std::invoke_result<const (lambda at sel/test/constant_test.cpp:26:7) &, int>'
  314 | using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
      | ^~~~~
external/skytest+/src/test.hpp:27:16: note: in instantiation of template type alias 'invoke_result_t' requested here
   27 |           std::invoke_result_t<const remove_cvref_t<F>&, Args...>,
      |                ^
external/toolchains_llvm++llvm+llvm_toolchain_llvm/bin/../include/c++/v1/__type_traits/conjunction.h:60:58: note: in instantiation of template class 'skytest::detail::returns_result<(lambda at sel/test/constant_test.cpp:26:7), int>' requested here
   60 | struct conjunction<_Arg, _Args...> : conditional_t<!bool(_Arg::value), _Arg, conjunction<_Args...>> {};
      |                                                          ^
external/skytest+/src/test_param.hpp:117:7: note: in instantiation of template class 'std::conjunction<skytest::detail::returns_result<(lambda at sel/test/constant_test.cpp:26:7), int>, skytest::detail::returns_result<(lambda at sel/test/constant_test.cpp:26:7), float>, skytest::detail::returns_result<(lambda at sel/test/constant_test.cpp:26:7), double>>' requested here
  117 |     : std::conjunction<returns_result<F, param_reference_t<Is, Params>>...>
      |       ^
external/skytest+/src/test_param.hpp:127:7: note: in instantiation of template class 'skytest::detail::param_invocable_<std::integer_sequence<unsigned long, 0, 1, 2>, (lambda at sel/test/constant_test.cpp:26:7), skytest::constexpr_params_t<1, 2.000000e+00, 3.000000e+00>>' requested here
  127 |     : param_invocable_<param_sequence_t<Params>, F, param_resolve_t<Params>>
      |       ^
external/skytest+/src/test_param.hpp:131:43: note: in instantiation of template class 'skytest::detail::param_invocable<(lambda at sel/test/constant_test.cpp:26:7), skytest::param_ref_t<skytest::constexpr_params_instance>>' requested here
  131 | inline constexpr auto param_invocable_v = param_invocable<F, Params>::value;
      |                                           ^
external/skytest+/src/test_param.hpp:252:11: note: in instantiation of variable template specialization 'skytest::detail::param_invocable_v' requested here
  252 |           param_invocable_v<F, params_type> and
      |           ^
external/skytest+/src/test_param.hpp:256:8: note: while substituting prior template arguments into non-type template parameter [with F = (lambda at sel/test/constant_test.cpp:26:7)]
  256 |   auto operator=(const F& func) && -> void
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  257 |   {
      |   ~
  258 |     assign_impl(
      |     ~~~~~~~~~~~~
  259 |         param_sequence_t<params_type>{},
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  260 |         param_bound_closure<F, params_type>{func, params_});
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  261 |   }
      |   ~
sel/test/constant_test.cpp:25:38: note: while substituting deduced template arguments into function template 'operator=' [with F = (lambda at sel/test/constant_test.cpp:26:7), $1 = (no value)]
   25 |       constexpr_params<1, 2.0F, 3.0> =  //
      |                                      ^
sel/test/constant_test.cpp:25:38: error: no viable overloaded '='
   24 |   "constants always define a strong ordering"_ctest *
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   25 |       constexpr_params<1, 2.0F, 3.0> =  //
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
   26 |       []<class T>(T value) {
      |       ~~~~~~~~~~~~~~~~~~~~~~
   27 |         auto a = sel::constant{value};
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   28 |         auto b = sel::constant{T{2} * value};
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   29 |         return expect(
      |         ~~~~~~~~~~~~~~
   30 |             eq(std::strong_ordering::less == (a <=> b)) and     //
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   31 |             eq(std::strong_ordering::greater, (b <=> a)) and  //
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   32 |             eq(std::strong_ordering::equal, (b <=> b))
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   33 |         );
      |         ~~
   34 |       };
      |       ~
external/skytest+/src/test_param.hpp:256:8: note: candidate template ignored: substitution failure [with F = (lambda at sel/test/constant_test.cpp:26:7)]
  256 |   auto operator=(const F& func) && -> void
      |        ^
external/skytest+/src/test_param.hpp:269:8: note: candidate template ignored: substitution failure [with F = (lambda at sel/test/constant_test.cpp:26:7)]
  269 |   auto operator=(const F& func) && -> void
      |        ^
external/skytest+/src/test_param.hpp:174:7: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from '(lambda at sel/test/constant_test.cpp:26:7)' to 'const parameterized_test<param_ref_t<skytest::constexpr_params_instance>, compile_time>' for 1st argument
  174 | class parameterized_test
      |       ^~~~~~~~~~~~~~~~~~
3 errors generated.
after
external/skytest+/src/detail/predicate.hpp:35:18: error: no matching function for call to object of type 'const std::equal_to<void>'
   35 |     auto value = static_cast<const F&>(*this)(std::as_const(args)...);
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
sel/test/constant_test.cpp:30:13: note: in instantiation of function template specialization 'skytest::detail::predicate<std::equal_to<void>, skytest::detail::type_name, skytest::detail::pred_fmt::eq_>::operator()<bool>' requested here
   30 |             eq(std::strong_ordering::less == (a <=> b)) and     //
      |             ^
external/skytest+/src/test_param.hpp:161:26: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<double>' requested here
  161 |       return [] { return func(get<I>(params)); };
      |                          ^
external/skytest+/src/test_param.hpp:161:17: note: while substituting into a lambda expression here
  161 |       return [] { return func(get<I>(params)); };
      |                 ^
external/skytest+/src/test_param.hpp:231:15: note: in instantiation of function template specialization 'skytest::detail::param_bound_static_closure<f, skytest::constexpr_params_instance>::operator[]<2UL>' requested here
  231 |               g[constant<Is>{}],
      |               ^
external/skytest+/src/test_param.hpp:253:7: note: in instantiation of function template specialization 'skytest::detail::parameterized_test<skytest::param_ref_t<skytest::constexpr_params_instance>, skytest::detail::test_style::compile_time>::assign_impl<0UL, 1UL, 2UL, skytest::detail::param_bound_static_closure<f, skytest::constexpr_params_instance>>' requested here
  253 |       assign_impl(
      |       ^
sel/test/constant_test.cpp:25:38: note: in instantiation of function template specialization 'skytest::detail::parameterized_test<skytest::param_ref_t<skytest::constexpr_params_instance>, skytest::detail::test_style::compile_time>::operator=<(lambda at sel/test/constant_test.cpp:26:7)>' requested here
   25 |       constexpr_params<1, 2.0F, 3.0> =  //
      |                                      ^
external/toolchains_llvm++llvm+llvm_toolchain_llvm/bin/../include/c++/v1/__functional/operations.h:308:60: note: candidate function template not viable: requires 2 arguments, but 1 was provided
  308 |   _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const
      |                                                            ^          ~~~~~~~~~~~~~~~~~~~~
1 error generated.

Change-Id: Ibc7ab9d85dc732ae7b895093147584211ef713ac

@oliverlee oliverlee force-pushed the Ibc7ab9d85dc732ae7b895093147584211ef713ac branch from db1da24 to b5b8aa4 Compare June 17, 2025 02:45
@codecov
Copy link

codecov bot commented Jun 17, 2025

Codecov Report

Attention: Patch coverage is 90.00000% with 1 line in your changes missing coverage. Please review.

Project coverage is 93.81%. Comparing base (e1ba769) to head (bbca292).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/test_param.hpp 85.71% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #44      +/-   ##
==========================================
- Coverage   93.84%   93.81%   -0.03%     
==========================================
  Files          15       15              
  Lines         276      275       -1     
  Branches       28       28              
==========================================
- Hits          259      258       -1     
  Misses          5        5              
  Partials       12       12              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Remove SFINAE from user-facing functions to reduce the length of compiler
errors. For example, the error for `eq(a == b)` instead of `eq(a, b)` is

<details><summary>before</summary>

```
external/toolchains_llvm++llvm+llvm_toolchain_llvm/bin/../include/c++/v1/__type_traits/invoke.h:314:1: error: no type named 'type' in 'std::invoke_result<const (lambda at sel/test/constant_test.cpp:26:7) &, int>'
  314 | using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
      | ^~~~~
external/skytest+/src/test.hpp:27:16: note: in instantiation of template type alias 'invoke_result_t' requested here
   27 |           std::invoke_result_t<const remove_cvref_t<F>&, Args...>,
      |                ^
external/toolchains_llvm++llvm+llvm_toolchain_llvm/bin/../include/c++/v1/__type_traits/conjunction.h:60:58: note: in instantiation of template class 'skytest::detail::returns_result<(lambda at sel/test/constant_test.cpp:26:7), int>' requested here
   60 | struct conjunction<_Arg, _Args...> : conditional_t<!bool(_Arg::value), _Arg, conjunction<_Args...>> {};
      |                                                          ^
external/skytest+/src/test_param.hpp:117:7: note: in instantiation of template class 'std::conjunction<skytest::detail::returns_result<(lambda at sel/test/constant_test.cpp:26:7), int>, skytest::detail::returns_result<(lambda at sel/test/constant_test.cpp:26:7), float>, skytest::detail::returns_result<(lambda at sel/test/constant_test.cpp:26:7), double>>' requested here
  117 |     : std::conjunction<returns_result<F, param_reference_t<Is, Params>>...>
      |       ^
external/skytest+/src/test_param.hpp:127:7: note: in instantiation of template class 'skytest::detail::param_invocable_<std::integer_sequence<unsigned long, 0, 1, 2>, (lambda at sel/test/constant_test.cpp:26:7), skytest::constexpr_params_t<1, 2.000000e+00, 3.000000e+00>>' requested here
  127 |     : param_invocable_<param_sequence_t<Params>, F, param_resolve_t<Params>>
      |       ^
external/skytest+/src/test_param.hpp:131:43: note: in instantiation of template class 'skytest::detail::param_invocable<(lambda at sel/test/constant_test.cpp:26:7), skytest::param_ref_t<skytest::constexpr_params_instance>>' requested here
  131 | inline constexpr auto param_invocable_v = param_invocable<F, Params>::value;
      |                                           ^
external/skytest+/src/test_param.hpp:252:11: note: in instantiation of variable template specialization 'skytest::detail::param_invocable_v' requested here
  252 |           param_invocable_v<F, params_type> and
      |           ^
external/skytest+/src/test_param.hpp:256:8: note: while substituting prior template arguments into non-type template parameter [with F = (lambda at sel/test/constant_test.cpp:26:7)]
  256 |   auto operator=(const F& func) && -> void
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  257 |   {
      |   ~
  258 |     assign_impl(
      |     ~~~~~~~~~~~~
  259 |         param_sequence_t<params_type>{},
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  260 |         param_bound_closure<F, params_type>{func, params_});
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  261 |   }
      |   ~
sel/test/constant_test.cpp:25:38: note: while substituting deduced template arguments into function template 'operator=' [with F = (lambda at sel/test/constant_test.cpp:26:7), $1 = (no value)]
   25 |       constexpr_params<1, 2.0F, 3.0> =  //
      |                                      ^
sel/test/constant_test.cpp:25:38: error: no viable overloaded '='
   24 |   "constants always define a strong ordering"_ctest *
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   25 |       constexpr_params<1, 2.0F, 3.0> =  //
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
   26 |       []<class T>(T value) {
      |       ~~~~~~~~~~~~~~~~~~~~~~
   27 |         auto a = sel::constant{value};
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   28 |         auto b = sel::constant{T{2} * value};
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   29 |         return expect(
      |         ~~~~~~~~~~~~~~
   30 |             eq(std::strong_ordering::less == (a <=> b)) and     //
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   31 |             eq(std::strong_ordering::greater, (b <=> a)) and  //
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   32 |             eq(std::strong_ordering::equal, (b <=> b))
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   33 |         );
      |         ~~
   34 |       };
      |       ~
external/skytest+/src/test_param.hpp:256:8: note: candidate template ignored: substitution failure [with F = (lambda at sel/test/constant_test.cpp:26:7)]
  256 |   auto operator=(const F& func) && -> void
      |        ^
external/skytest+/src/test_param.hpp:269:8: note: candidate template ignored: substitution failure [with F = (lambda at sel/test/constant_test.cpp:26:7)]
  269 |   auto operator=(const F& func) && -> void
      |        ^
external/skytest+/src/test_param.hpp:174:7: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from '(lambda at sel/test/constant_test.cpp:26:7)' to 'const parameterized_test<param_ref_t<skytest::constexpr_params_instance>, compile_time>' for 1st argument
  174 | class parameterized_test
      |       ^~~~~~~~~~~~~~~~~~
3 errors generated.
```

</details>

<details><summary>after</summary>

```
external/skytest+/src/detail/predicate.hpp:35:18: error: no matching function for call to object of type 'const std::equal_to<void>'
   35 |     auto value = static_cast<const F&>(*this)(std::as_const(args)...);
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
sel/test/constant_test.cpp:30:13: note: in instantiation of function template specialization 'skytest::detail::predicate<std::equal_to<void>, skytest::detail::type_name, skytest::detail::pred_fmt::eq_>::operator()<bool>' requested here
   30 |             eq(std::strong_ordering::less == (a <=> b)) and     //
      |             ^
external/skytest+/src/test_param.hpp:161:26: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<double>' requested here
  161 |       return [] { return func(get<I>(params)); };
      |                          ^
external/skytest+/src/test_param.hpp:161:17: note: while substituting into a lambda expression here
  161 |       return [] { return func(get<I>(params)); };
      |                 ^
external/skytest+/src/test_param.hpp:231:15: note: in instantiation of function template specialization 'skytest::detail::param_bound_static_closure<f, skytest::constexpr_params_instance>::operator[]<2UL>' requested here
  231 |               g[constant<Is>{}],
      |               ^
external/skytest+/src/test_param.hpp:253:7: note: in instantiation of function template specialization 'skytest::detail::parameterized_test<skytest::param_ref_t<skytest::constexpr_params_instance>, skytest::detail::test_style::compile_time>::assign_impl<0UL, 1UL, 2UL, skytest::detail::param_bound_static_closure<f, skytest::constexpr_params_instance>>' requested here
  253 |       assign_impl(
      |       ^
sel/test/constant_test.cpp:25:38: note: in instantiation of function template specialization 'skytest::detail::parameterized_test<skytest::param_ref_t<skytest::constexpr_params_instance>, skytest::detail::test_style::compile_time>::operator=<(lambda at sel/test/constant_test.cpp:26:7)>' requested here
   25 |       constexpr_params<1, 2.0F, 3.0> =  //
      |                                      ^
external/toolchains_llvm++llvm+llvm_toolchain_llvm/bin/../include/c++/v1/__functional/operations.h:308:60: note: candidate function template not viable: requires 2 arguments, but 1 was provided
  308 |   _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const
      |                                                            ^          ~~~~~~~~~~~~~~~~~~~~
1 error generated.
```

</details>

Change-Id: Ibc7ab9d85dc732ae7b895093147584211ef713ac
@oliverlee oliverlee force-pushed the Ibc7ab9d85dc732ae7b895093147584211ef713ac branch from b5b8aa4 to bbca292 Compare June 17, 2025 02:49
@oliverlee oliverlee merged commit 6446f9c into main Jun 17, 2025
13 of 15 checks passed
@oliverlee oliverlee deleted the Ibc7ab9d85dc732ae7b895093147584211ef713ac branch June 17, 2025 02:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant