Type errors for RPC callbacks returning types with asymmetric serialization

Issue #394 resolved
Amir Kamil created an issue

RPC callbacks that return a type with asymmetric serialization fail to compile.

Example:

#include <upcxx/upcxx.hpp>

template<typename T, typename U>
struct assert_same {
  static_assert(std::is_same<T, U>::value, "differ");
};

struct D {
  int w,x;
};
struct S { // asymmetric serialization
  int x,y,z;
  struct upcxx_serialization {
    template<typename Writer>
    static void serialize (Writer& writer, S const & t) {
        writer.write(t.x);
    }
    template<typename Reader>
    static D* deserialize(Reader& reader, void* storage) {
        int x = reader.template read<int>();
        D *up = new(storage) D();
        up->x = x;
        return up;
    }
  };
};

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

  {
    auto res = upcxx::rpc((upcxx::rank_me() + 1) % upcxx::rank_n(),
      []() {
        return S{1, 2, 3};
      });
    assert_same<decltype(res), upcxx::future<D>>{};
    UPCXX_ASSERT_ALWAYS(res.wait().x == 1);
  }

  upcxx::finalize();
}

Error with GCC 9 on the develop branch:

In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/dist_object.hpp:7,
                 from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:12,
                 from /Users/akamil/work/tmp/upcxx/issue394.cpp:1:
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp: In instantiation of 'void upcxx::detail::rpc_recipient_after<upcxx::detail::lpc_dormant<T ...>*>::operator()(Arg&& ...) const [with Arg = {S}; T = {D}]':
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/apply.hpp:32:29:   required from 'upcxx::detail::apply_tupled_as_future_dispatch<FnRef, ArgRefTupRef, upcxx::detail::index_sequence<i ...>, void>::return_type upcxx::detail::apply_tupled_as_future_dispatch<FnRef, ArgRefTupRef, upcxx::detail::index_sequence<i ...>, void>::operator()(FnRef, ArgRefTupRef) [with FnRef = upcxx::detail::rpc_recipient_after<upcxx::detail::lpc_dormant<D>*>&&; ArgRefTupRef = std::tuple<S&&>&&; int ...ai = {0}; upcxx::detail::apply_tupled_as_future_dispatch<FnRef, ArgRefTupRef, upcxx::detail::index_sequence<i ...>, void>::return_type = upcxx::future1<upcxx::detail::future_kind_result>]'
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/apply.hpp:160:22:   required from 'upcxx::detail::apply_futured_as_future_help<FnRef, ArgFuRef, upcxx::future1<Kind, T ...> >::return_type upcxx::detail::apply_futured_as_future_help<FnRef, ArgFuRef, upcxx::future1<Kind, T ...> >::operator()(FnRef, ArgFuRef) [with FnRef = upcxx::detail::rpc_recipient_after<upcxx::detail::lpc_dormant<D>*>&&; ArgFuRef = upcxx::future1<upcxx::detail::future_kind_result, S>&&; Kind = upcxx::detail::future_kind_result; T = {S}; upcxx::detail::apply_futured_as_future_help<FnRef, ArgFuRef, upcxx::future1<Kind, T ...> >::return_type = upcxx::future1<upcxx::detail::future_kind_result>]'
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/then.hpp:184:56:   required from 'upcxx::detail::future_then<Arg, Fn, return_lazy, upcxx::future1<Kind, T ...>, true>::return_type upcxx::detail::future_then<Arg, Fn, return_lazy, upcxx::future1<Kind, T ...>, true>::operator()(Arg1&&, Fn1&&) [with Arg1 = upcxx::future1<upcxx::detail::future_kind_result, S>; Fn1 = upcxx::detail::rpc_recipient_after<upcxx::detail::lpc_dormant<D>*>; Arg = upcxx::future1<upcxx::detail::future_kind_result, S>; Fn = upcxx::detail::rpc_recipient_after<upcxx::detail::lpc_dormant<D>*>; bool return_lazy = true; FnRetKind = upcxx::detail::future_kind_result; FnRetT = {}; upcxx::detail::future_then<Arg, Fn, return_lazy, upcxx::future1<Kind, T ...>, true>::return_type = upcxx::future1<upcxx::detail::future_kind_result>]'
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/future1.hpp:289:106:   required from 'typename upcxx::detail::future_then<upcxx::future1<Kind, T>, typename std::decay<_Functor>::type, true>::return_type upcxx::future1<Kind, T>::then_lazy(Fn&&) && [with Fn = upcxx::detail::rpc_recipient_after<upcxx::detail::lpc_dormant<D>*>; Kind = upcxx::detail::future_kind_result; T = {S}; typename upcxx::detail::future_then<upcxx::future1<Kind, T>, typename std::decay<_Functor>::type, true>::return_type = upcxx::future1<upcxx::detail::future_kind_result>]'
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:295:15:   required from 'typename upcxx::detail::rpc_return<Fn(Arg ...), Cxs>::type upcxx::detail::rpc(const upcxx::team&, upcxx::intrank_t, Cxs, Fn&&, Arg&& ...) [with Cxs = upcxx::completions<upcxx::future_cx<upcxx::operation_cx_event, upcxx::progress_level::user> >; Fn = main()::<lambda()>&&; Arg = {}; typename upcxx::detail::rpc_return<Fn(Arg ...), Cxs>::type = upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, D>; upcxx::intrank_t = int]'
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:358:92:   required from 'typename upcxx::detail::rpc_return<Fn(Arg ...), upcxx::completions<upcxx::future_cx<upcxx::operation_cx_event, upcxx::progress_level::user> > >::type upcxx::rpc(upcxx::intrank_t, Fn&&, Arg&& ...) [with Fn = main()::<lambda()>; Arg = {}; typename upcxx::detail::rpc_return<Fn(Arg ...), upcxx::completions<upcxx::future_cx<upcxx::operation_cx_event, upcxx::progress_level::user> > >::type = upcxx::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, D>; upcxx::intrank_t = int]'
/Users/akamil/work/tmp/upcxx/issue394.cpp:35:8:   required from here
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:193:28: error: no matching function for call to 'std::tuple<D>::tuple(S)'
  193 |           remote_lpc, std::tuple<T...>(std::forward<Arg>(arg)...)
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/fwd.hpp:4,
                 from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend_fwd.hpp:21,
                 from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend.hpp:4,
                 from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/allocate.hpp:8,
                 from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:5,
                 from /Users/akamil/work/tmp/upcxx/issue394.cpp:1:

Comments (3)

  1. Dan Bonachea

    Based on poking older releases, this is NOT a recent regression - it appears this has never worked correctly!

  2. Log in to comment