when_all not accepting the documented template arguments

Issue #396 resolved
Dan Bonachea created an issue

when_all does not appear to be accepting the documented template arguments.

Latest development spec for when_all:

when_all.png

Test program:

#include <upcxx/upcxx.hpp>

using namespace upcxx;

int main() {
  upcxx::init();

  future<int> f = make_future(1);
  future<int,int> f2 = when_all(f,f);
  future<int,int> f3 = when_all<future<int>,future<int>>(f,f);

  upcxx::finalize();
  return 0;
}

Compile errors (dirac/gcc-10.2/ibv/seq/debug): upcxx-2020.3.7-1-g c3da283

whenall-bug.cc: In function 'int main()':
whenall-bug.cc:11:61: error: no matching function for call to 'when_all<upcxx::future<int>, upcxx::future<int> >(upcxx::future<int>&, upcxx::future<int>&)'
   11 |   future<int,int> f3 = when_all<future<int>,future<int>>(f,f);
      |                                                             ^
In file included from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/future.hpp:11,
                 from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/backend.hpp:5,
                 from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/allocate.hpp:8,
                 from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/upcxx.hpp:5,
                 from whenall-bug.cc:1:
/usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/future/when_all.hpp:68:39: note: candidate: 'upcxx::detail::when_all_return_t<ArgFu ...> upcxx::when_all(ArgFu&& ...) [with ArgFu = {upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general, false>, int>, upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general, false>, int>}; upcxx::detail::when_all_return_t<ArgFu ...> = upcxx::future1<upcxx::detail::future_kind_when_all<upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general, false>, int>, upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general, false>, int> >, int, int>]' (near match)
   68 |   detail::when_all_return_t<ArgFu...> when_all(ArgFu &&...arg) {
      |                                       ^~~~~~~~
/usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/future/when_all.hpp:68:39: note:   conversion of argument 2 would be ill-formed:
whenall-bug.cc:11:60: error: cannot bind rvalue reference of type 'upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, int>&&' to lvalue of type 'upcxx::future<int>' {aka 'upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, int>'}
   11 |   future<int,int> f3 = when_all<future<int>,future<int>>(f,f);
      |                                                            ^
In file included from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/future.hpp:11,
                 from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/backend.hpp:5,
                 from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/allocate.hpp:8,
                 from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/upcxx.hpp:5,
                 from whenall-bug.cc:1:
/usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/future/when_all.hpp:75:11: note: candidate: 'template<class ArgFu> ArgFu&& upcxx::when_all(ArgFu&&)'
   75 |   ArgFu&& when_all(ArgFu &&arg) {
      |           ^~~~~~~~
/usr/local/pkg/upcxx-dirac/gcc-10.2.0/nightly-2020.07.28/upcxx.debug.gasnet_seq.ibv/include/upcxx/future/when_all.hpp:75:11: note:   template argument deduction/substitution failed:
whenall-bug.cc:11:61: error: wrong number of template arguments (2, should be 1)
   11 |   future<int,int> f3 = when_all<future<int>,future<int>>(f,f);
      |                                                             ^

Comments (3)

  1. Amir Kamil

    The implementation takes its arguments by universal reference, which differs from the by-value arguments in the spec. We need to fix this discrepancy.

    Summarizing from a Slack discussion with @Dan Bonachea , he would like to construct a future<int&> by explicitly instantiating when_all with template arguments. I do not believe this to be possible given that it takes arguments by universal reference. We can’t tell what the user intent is from the argument type being an lvalue reference. Maybe they want a reference inside a future, maybe they just want to avoid a copy when calling when_all, or maybe they just happened to pass an lvalue to when_all without thinking about it.

    The workaround is to explicitly call make_future in this case. I don’t think this will be a common case.

  2. Amir Kamil

    Just to add an explanation of the compiler error, instantiating when_all<future<int>,future<int>> forces the function parameters to be rvalue references, while the arguments are lvalues.

  3. Log in to comment