Regression in rpc(team,rank,..,view) overload resolution leads to confusing type errors

Issue #428 resolved
Dan Bonachea created an issue

Example program:

#include <upcxx/upcxx.hpp>
#include <iostream>

using namespace upcxx;

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

  constexpr int N = 100;
  char A[N];
  auto myview = make_view(A, A+N);

  {
    auto f = rpc(0, [](view<char> const &){}, myview);
    f.wait();
  }

  {
    auto f = rpc(world(), 0, [](view<char> const &){}, myview);
    f.wait();
  }

  upcxx::finalize();
  return 0;
}

Typechecking for this simple program has broken as of release 2020.10.0 (and also 2020.11.0), leading to overload resolution errors (eg gcc 10.2.0):

rpc-overload.cpp: In function 'int main()':
rpc-overload.cpp:19:62: error: call of overloaded 'rpc(upcxx::team&, int, main()::<lambda(const upcxx::view<char, char*>&)>, upcxx::view<char, char*>&)' is ambiguous
   19 |     auto f = rpc(world(), 0, [](view<char> const &){}, myview);
      |                                                              ^
In file included from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/stable-2020.10.0/upcxx.debug.gasnet_seq.ibv/include/upcxx/dist_object.hpp:7,
                 from /usr/local/pkg/upcxx-dirac/gcc-10.2.0/stable-2020.10.0/upcxx.debug.gasnet_seq.ibv/include/upcxx/upcxx.hpp:12,
                 from rpc-overload.cpp:1:
/usr/local/pkg/upcxx-dirac/gcc-10.2.0/stable-2020.10.0/upcxx.debug.gasnet_seq.ibv/include/upcxx/rpc.hpp:480:8: note: candidate: 'typename std::enable_if<(! upcxx::detail::is_completions<Fn>::value), typename upcxx::detail::rpc_return_no_sfinae<Fn(Arg ...), upcxx::completions<upcxx::future_cx<upcxx::operation_cx_event, upcxx::progress_level::user> > >::type>::type upcxx::rpc(const upcxx::team&, upcxx::intrank_t, Fn&&, Arg&& ...) [with Fn = main()::<lambda(const upcxx::view<char, char*>&)>; Arg = {upcxx::view<char, char*>&}; typename std::enable_if<(! upcxx::detail::is_completions<Fn>::value), typename upcxx::detail::rpc_return_no_sfinae<Fn(Arg ...), upcxx::completions<upcxx::future_cx<upcxx::operation_cx_event, upcxx::progress_level::user> > >::type>::type = upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general> >; upcxx::intrank_t = int]'
  480 |   auto rpc(const team &tm, intrank_t recipient, Fn &&fn, Arg &&...args)
      |        ^~~
/usr/local/pkg/upcxx-dirac/gcc-10.2.0/stable-2020.10.0/upcxx.debug.gasnet_seq.ibv/include/upcxx/rpc.hpp:421:14: note: candidate: 'upcxx::future<> upcxx::detail::rpc(const upcxx::team&, upcxx::intrank_t, Fn&&, Arg&& ..., Cxs&&, ...) [with Cxs = upcxx::view<char, char*>&; Fn = main()::<lambda(const upcxx::view<char, char*>&)>; Arg = {}; upcxx::future<> = upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general> >; upcxx::intrank_t = int]'
  421 |     future<> rpc(const team &, intrank_t, Fn &&, Arg &&..., Cxs&&, ...) {
      |              ^~~

and/or spurious static assertions (eg clang 11.0):

In file included from rpc-overload.cpp:1:
In file included from /usr/local/pkg/upcxx-dirac/clang-11.0.0/stable-2020.10.0/upcxx.debug.gasnet_seq.ibv/include/upcxx/upcxx.hpp:12:
In file included from /usr/local/pkg/upcxx-dirac/clang-11.0.0/stable-2020.10.0/upcxx.debug.gasnet_seq.ibv/include/upcxx/dist_object.hpp:7:
/usr/local/pkg/upcxx-dirac/clang-11.0.0/stable-2020.10.0/upcxx.debug.gasnet_seq.ibv/include/upcxx/rpc.hpp:429:7: error: static_assert failed due to requirement 'detail::rpc_return_no_sfinae<(lambda at rpc-overload.cpp:19:30) (), upcxx::view<char, char *>, void>::value' "function object provided to rpc cannot be invoked on the given arguments as rvalue references (after deserialization of the function object and arguments). Note: make sure that the function object does not have any non-const lvalue-reference parameters."
      static_assert(
      ^
rpc-overload.cpp:19:14: note: in instantiation of function template specialization 'upcxx::detail::rpc<upcxx::view<char, char *> &, (lambda at rpc-overload.cpp:19:30)>' requested here
    auto f = rpc(world(), 0, [](view<char> const &){}, myview);
             ^
1 error generated.

The problem is the unqualified call to rpc(team, rank, ...) is being resolved ambiguously due to an incorrectly/inadvertently included internal function overload detail::rpc (which appears to get pulled in via ADL on the view argument).

The recommended workaround for users is to explicitly qualify the problematic call with a namespace (ie upcxx::rpc(...)).

Comments (2)

  1. Dan Bonachea reporter

    issue #428: Regression in rpc(team,rank,..,view) overload resolution leads to confusing type errors

    Name-shift the internal function names in the detail namespace, improving readability and guaranteeing they will never participate in overload resolution for the public API.

    Fixes issue #428

    → <<cset 882a442b044f>>

  2. Log in to comment