RPC breaks if an argument asymmetrically deserializes to a type that itself has asymmetric deserialization

Issue #407 resolved
Amir Kamil created an issue

Sample code:

#include <upcxx/upcxx.hpp>

struct C {
  int x;
};

struct B {
  int x;
  struct upcxx_serialization {
    template<typename Writer>
    static void serialize(Writer &w, const B &a) {
      w.write(a.x);
    }
    template<typename Reader>
    static C* deserialize(Reader &r, void *spot) {
      return new(spot) C{r.template read<int>()};
    }
  };
};

struct A {
  int x;
  struct upcxx_serialization {
    template<typename Writer>
    static void serialize(Writer &w, const A &a) {
      w.write(a.x);
    }
    template<typename Reader>
    static B* deserialize(Reader &r, void *spot) {
      return new(spot) B{r.template read<int>()};
    }
  };
};

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

  upcxx::rpc(0,[](B const &a) {
                 assert(a.x == 10); 
               }, A{10}).wait();

  upcxx::finalize();
}

Sample compiler error:

In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:5:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/allocate.hpp:8:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend.hpp:7:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/team.hpp:4:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/team_fwd.hpp:4:
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/bind.hpp:145:12: error: 
      no type named 'type' in 'std::__1::result_of<(lambda at
      ../../upcxx-akamil/bar.cpp:38:16) &&(C &&)>'
        >::type
        ~~~^~~~
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/bind.hpp:206:7: note: 
      in instantiation of template class
      'upcxx::detail::bound_function_base<(lambda at
      ../../upcxx-akamil/bar.cpp:38:16), std::__1::tuple<B>,
      upcxx::detail::index_sequence<0>, true>' requested here
      detail::bound_function_base<Fn, std::tuple<B...>> {
      ^
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:392:17: note: 
      in instantiation of template class 'upcxx::bound_function<(lambda at
      ../../upcxx-akamil/bar.cpp:38:16), B>' requested here
                static_cast<deserialized_type_t<fn_bound_t>&&>(fn_bound)
                ^
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:507:29: note: 
      in instantiation of function template specialization
      'upcxx::detail::rpc<upcxx::completions<upcxx::future_cx<upcxx::operation_cx_event,
      upcxx::progress_level::user> >, (lambda at
      ../../upcxx-akamil/bar.cpp:38:16) &&, A &&>' requested here
    return detail::template rpc<completions<future_cx<operation_cx_event...
                            ^
../../upcxx-akamil/bar.cpp:38:10: note: in instantiation of function template
      specialization 'upcxx::rpc<(lambda at ../../upcxx-akamil/bar.cpp:38:16),
      A>' requested here
  upcxx::rpc(0,[](B const &a) {
         ^
In file included from ../../upcxx-akamil/bar.cpp:1:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:5:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/allocate.hpp:8:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend.hpp:5:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future.hpp:7:
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/apply.hpp:119:50: error: 
      no type named 'type' in 'std::__1::result_of<upcxx::bound_function<(lambda
      at ../../upcxx-akamil/bar.cpp:38:16), B> &&()>'
      typename std::result_of<FnRef(ArgRef...)>::type
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/apply.hpp:183:20: note: 
      in instantiation of template class
      'upcxx::detail::apply_variadic_as_future<upcxx::bound_function<(lambda at
      ../../upcxx-akamil/bar.cpp:38:16), B> &&>' requested here
  typename detail::apply_variadic_as_future<Fn&&, Arg&&...>::return_type
                   ^
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:391:20: note: 
      while substituting deduced template arguments into function template
      'apply_as_future' [with Fn = upcxx::bound_function<(lambda at
      ../../upcxx-akamil/bar.cpp:38:16), B>, Arg = <>]
            return upcxx::apply_as_future(
                   ^
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:507:29: note: 
      in instantiation of function template specialization
      'upcxx::detail::rpc<upcxx::completions<upcxx::future_cx<upcxx::operation_cx_event,
      upcxx::progress_level::user> >, (lambda at
      ../../upcxx-akamil/bar.cpp:38:16) &&, A &&>' requested here
    return detail::template rpc<completions<future_cx<operation_cx_event...
                            ^
../../upcxx-akamil/bar.cpp:38:10: note: in instantiation of function template
      specialization 'upcxx::rpc<(lambda at ../../upcxx-akamil/bar.cpp:38:16),
      A>' requested here
  upcxx::rpc(0,[](B const &a) {
         ^
In file included from ../../upcxx-akamil/bar.cpp:1:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:12:
In file included from /Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/dist_object.hpp:7:
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:391:20: error: 
      no matching function for call to 'apply_as_future'
            return upcxx::apply_as_future(
                   ^~~~~~~~~~~~~~~~~~~~~~
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:507:29: note: 
      in instantiation of function template specialization
      'upcxx::detail::rpc<upcxx::completions<upcxx::future_cx<upcxx::operation_cx_event,
      upcxx::progress_level::user> >, (lambda at
      ../../upcxx-akamil/bar.cpp:38:16) &&, A &&>' requested here
    return detail::template rpc<completions<future_cx<operation_cx_event...
                            ^
../../upcxx-akamil/bar.cpp:38:10: note: in instantiation of function template
      specialization 'upcxx::rpc<(lambda at ../../upcxx-akamil/bar.cpp:38:16),
      A>' requested here
  upcxx::rpc(0,[](B const &a) {
         ^
/Users/akamil/work/tmp/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/apply.hpp:184:3: note: 
      candidate template ignored: substitution failure [with Fn =
      upcxx::bound_function<(lambda at ../../upcxx-akamil/bar.cpp:38:16), B>,
      Arg = <>]
  apply_as_future(Fn &&fn, Arg &&...arg) {
  ^
3 errors generated.

This will be nontrivial to fix. A bound_function<T...> deserializes as a bound_function<deserialized_type_t<T>...>, and bound_function<U...>::operator() works (more or less) with deserialized_type_t<U>.... There are some nuances in the implementation (a rather complicated set of type aliases contained in a binding<T>).

Comments (2)

  1. Log in to comment