Compilation errors for write and read_into on a multidimensional array

Issue #552 resolved
Amir Kamil created an issue

The spec states the following for read_into<T>() (and similarly for write<T>()):

T must be Serializable or a (possibly multidimensional) array of Serializable element type.

Thus, invocations such as write<int[2][3]>(...) or read_into<std::string[2][3]>(...) should be valid. However, in the current implementation, they result in compilation errors.

Test code:

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

struct foo {
  int data[2][3];
  void fill(int value) {
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 3; ++j) {
        data[i][j] = value;
      }
    }
  }
  bool operator==(const foo &other) const {
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 3; ++j) {
        if (data[i][j] != other.data[i][j]) {
          return false;
        }
      }
    }
    return true;
  }
  struct upcxx_serialization {
    template<typename Writer>
    static void serialize(Writer &w, const foo &x) {
      w.write(x.data);
    }
    template<typename Reader>
    static foo* deserialize(Reader &r, void *spot) {
      auto result = new(spot) foo;
      r.template read_into<int[2][3]>(result->data);
      return result;
    }
  };
};

struct bar {
  std::string data[2][3];
  void fill(const std::string &value) {
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 3; ++j) {
        data[i][j] = value;
      }
    }
  }
  bool operator==(const bar &other) const {
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 3; ++j) {
        if (data[i][j] != other.data[i][j]) {
          return false;
        }
      }
    }
    return true;
  }
  struct upcxx_serialization {
    template<typename Writer>
    static void serialize(Writer &w, const bar &x) {
      w.write(x.data);
    }
    template<typename Reader>
    static bar* deserialize(Reader &r, void *spot) {
      auto result = new(spot) bar;
      r.template read_into<std::string[2][3]>(result->data);
      return result;
    }
  };
};

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

  int target = (upcxx::rank_me()+1) % upcxx::rank_n();

  foo f;
  f.fill(100 + target);

  upcxx::rpc(
    target,
    [](foo x) {
      foo expected;
      expected.fill(100 + upcxx::rank_me());
      UPCXX_ASSERT_ALWAYS(x == expected);
    },
    f).wait();

  bar b;
  b.fill(std::to_string(100 + target));

  upcxx::rpc(
    target,
    [](bar x) {
      bar expected;
      expected.fill(std::to_string(100 + upcxx::rank_me()));
      UPCXX_ASSERT_ALWAYS(x == expected);
    },
    b).wait();

  // quiesce the world
  upcxx::barrier();

  upcxx::finalize();
}

Errors:

$ ./bin/upcxx -g baz.cpp
INFO: may need to build the required runtime.  Please be patient.
In file included from baz.cpp:3:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:5:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/allocate.hpp:8:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend.hpp:4:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend_fwd.hpp:28:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/ccs_fwd.hpp:14:
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/utility.hpp:177:15: error: incompatible pointer types assigning to 'T1 *' (aka 'int (*)[3]') from 'int *'
        ans = ::new((T1*)dest + --i) T1;
              ^~
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/utility.hpp:206:27: note: in instantiation of function template specialization 'upcxx::detail::help::construct_trivial<int [3]>' requested here
    return help::template construct_trivial<T>(
                          ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:697:33: note: in instantiation of function template specialization 'upcxx::detail::construct_trivial<int [3]>' requested here
        return detail::template construct_trivial<T1>(raw, this->unplace(ss), n);
                                ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:715:31: note: in instantiation of function template specialization 'upcxx::detail::serialization_reader::read_sequence_into_<int [3], int [3]>' requested here
        return this->template read_sequence_into_<T,T1>(raw, n,
                              ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:1782:52: note: in instantiation of function template specialization 'upcxx::detail::serialization_reader::read_sequence_into<int [3], int [3]>' requested here
      return reinterpret_cast<T1(*)[n]>(r.template read_sequence_into<T>(raw, n));
                                                   ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:659:60: note: in instantiation of function template specialization 'upcxx::serialization<int [2][3]>::deserialize<upcxx::detail::serialization_reader>' requested here
        T1* res = upcxx::template serialization_traits<T>::deserialize(*this, raw);
                                                           ^
baz.cpp:32:18: note: (skipping 13 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
      r.template read_into<int[2][3]>(result->data);
                 ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend/gasnet/runtime.hpp:535:50: note: in instantiation of function template specialization 'upcxx::detail::command<upcxx::detail::lpc_base *>::serialize<&upcxx::backend::gasnet::rpc_as_lpc::reader_of, &upcxx::backend::gasnet::rpc_as_lpc::cleanup, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:81:5) &, const foo &> &> &, upcxx::detail::serialization_writer<false>, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:81:5) &, const foo &> &>>' requested here
    detail::command<detail::lpc_base*>::template serialize<
                                                 ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend/gasnet/runtime.hpp:560:27: note: in instantiation of function template specialization 'upcxx::backend::prepare_am<1, -1, false, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:81:5) &, const foo &> &>, false>' requested here
        level, recipient, prepare_am<1>(std::forward<Fn>(fn), recipient)
                          ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:467:25: note: in instantiation of function template specialization 'upcxx::backend::send_am_master<upcxx::progress_level::user, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:81:5) &, const foo &> &>>' requested here
      backend::template send_am_master<progress_level::user>(
                        ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:593:29: note: in instantiation of function template specialization 'upcxx::detail::rpc_internal<upcxx::detail::completions<upcxx::detail::future_cx<upcxx::operation_cx_event, true, upcxx::progress_level::user>>, (lambda at baz.cpp:81:5) &&, foo &>' requested here
    return detail::template rpc_internal<detail::operation_cx_as_future_t, Fn&&, Arg&&...>(
                            ^
baz.cpp:79:10: note: in instantiation of function template specialization 'upcxx::rpc<(lambda at baz.cpp:81:5), foo &>' requested here
  upcxx::rpc(
         ^
In file included from baz.cpp:3:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:5:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/allocate.hpp:8:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend.hpp:7:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/team.hpp:4:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/team_fwd.hpp:4:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/bind.hpp:6:
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:616:9: error: static_assert failed due to requirement 'is_serializable<int [3]>::value' "value_type of iterators passed to write_sequence must be Serializable."
        static_assert(is_serializable<T>::value,
        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:1771:9: note: in instantiation of function template specialization 'upcxx::detail::serialization_writer<false>::write_sequence<int const (*)[3]>' requested here
      w.write_sequence(&x[0], &x[0] + n, n);
        ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:323:50: note: in instantiation of function template specialization 'upcxx::serialization<int [2][3]>::serialize<upcxx::detail::serialization_writer<false>>' requested here
        upcxx::template serialization_traits<T>::serialize(*static_cast<Writer*>(this), x);
                                                 ^
baz.cpp:27:9: note: in instantiation of function template specialization 'upcxx::detail::serialization_writer_base<upcxx::detail::serialization_writer<false>>::write<int [2][3], true>' requested here
      w.write(x.data);
        ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:323:50: note: in instantiation of function template specialization 'foo::upcxx_serialization::serialize<upcxx::detail::serialization_writer<false>>' requested here
        upcxx::template serialization_traits<T>::serialize(*static_cast<Writer*>(this), x);
                                                 ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/bind.hpp:351:21: note: in instantiation of function template specialization 'upcxx::detail::serialization_writer_base<upcxx::detail::serialization_writer<false>>::write<const foo &, true>' requested here
        (w.template write<typename detail::binding<B>::on_wire_type>(
                    ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/bind.hpp:339:7: note: (skipping 5 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
      serialize_args(w, fn, detail::make_index_sequence<sizeof...(B)>());
      ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend/gasnet/runtime.hpp:535:50: note: in instantiation of function template specialization 'upcxx::detail::command<upcxx::detail::lpc_base *>::serialize<&upcxx::backend::gasnet::rpc_as_lpc::reader_of, &upcxx::backend::gasnet::rpc_as_lpc::cleanup, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:81:5) &, const foo &> &> &, upcxx::detail::serialization_writer<false>, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:81:5) &, const foo &> &>>' requested here
    detail::command<detail::lpc_base*>::template serialize<
                                                 ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend/gasnet/runtime.hpp:560:27: note: in instantiation of function template specialization 'upcxx::backend::prepare_am<1, -1, false, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:81:5) &, const foo &> &>, false>' requested here
        level, recipient, prepare_am<1>(std::forward<Fn>(fn), recipient)
                          ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:467:25: note: in instantiation of function template specialization 'upcxx::backend::send_am_master<upcxx::progress_level::user, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:81:5) &, const foo &> &>>' requested here
      backend::template send_am_master<progress_level::user>(
                        ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:593:29: note: in instantiation of function template specialization 'upcxx::detail::rpc_internal<upcxx::detail::completions<upcxx::detail::future_cx<upcxx::operation_cx_event, true, upcxx::progress_level::user>>, (lambda at baz.cpp:81:5) &&, foo &>' requested here
    return detail::template rpc_internal<detail::operation_cx_as_future_t, Fn&&, Arg&&...>(
                            ^
baz.cpp:79:10: note: in instantiation of function template specialization 'upcxx::rpc<(lambda at baz.cpp:81:5), foo &>' requested here
  upcxx::rpc(
         ^
In file included from baz.cpp:3:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:5:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/allocate.hpp:8:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend.hpp:7:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/team.hpp:4:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/team_fwd.hpp:4:
In file included from /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/bind.hpp:6:
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:616:9: error: static_assert failed due to requirement 'is_serializable<std::string [3]>::value' "value_type of iterators passed to write_sequence must be Serializable."
        static_assert(is_serializable<T>::value,
        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:1771:9: note: in instantiation of function template specialization 'upcxx::detail::serialization_writer<false>::write_sequence<std::string const (*)[3]>' requested here
      w.write_sequence(&x[0], &x[0] + n, n);
        ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:323:50: note: in instantiation of function template specialization 'upcxx::serialization<std::string [2][3]>::serialize<upcxx::detail::serialization_writer<false>>' requested here
        upcxx::template serialization_traits<T>::serialize(*static_cast<Writer*>(this), x);
                                                 ^
baz.cpp:60:9: note: in instantiation of function template specialization 'upcxx::detail::serialization_writer_base<upcxx::detail::serialization_writer<false>>::write<std::string [2][3], true>' requested here
      w.write(x.data);
        ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/serialization.hpp:323:50: note: in instantiation of function template specialization 'bar::upcxx_serialization::serialize<upcxx::detail::serialization_writer<false>>' requested here
        upcxx::template serialization_traits<T>::serialize(*static_cast<Writer*>(this), x);
                                                 ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/bind.hpp:351:21: note: in instantiation of function template specialization 'upcxx::detail::serialization_writer_base<upcxx::detail::serialization_writer<false>>::write<const bar &, true>' requested here
        (w.template write<typename detail::binding<B>::on_wire_type>(
                    ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/bind.hpp:339:7: note: (skipping 5 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
      serialize_args(w, fn, detail::make_index_sequence<sizeof...(B)>());
      ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend/gasnet/runtime.hpp:535:50: note: in instantiation of function template specialization 'upcxx::detail::command<upcxx::detail::lpc_base *>::serialize<&upcxx::backend::gasnet::rpc_as_lpc::reader_of, &upcxx::backend::gasnet::rpc_as_lpc::cleanup, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:93:5) &, const bar &> &> &, upcxx::detail::serialization_writer<false>, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:93:5) &, const bar &> &>>' requested here
    detail::command<detail::lpc_base*>::template serialize<
                                                 ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend/gasnet/runtime.hpp:560:27: note: in instantiation of function template specialization 'upcxx::backend::prepare_am<1, -1, false, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:93:5) &, const bar &> &>, false>' requested here
        level, recipient, prepare_am<1>(std::forward<Fn>(fn), recipient)
                          ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:467:25: note: in instantiation of function template specialization 'upcxx::backend::send_am_master<upcxx::progress_level::user, upcxx::detail::bound_function<const (lambda at /Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:470:11) &, const upcxx::detail::bound_function<const (lambda at baz.cpp:93:5) &, const bar &> &>>' requested here
      backend::template send_am_master<progress_level::user>(
                        ^
/Users/akamil/work/upcxx/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/rpc.hpp:593:29: note: in instantiation of function template specialization 'upcxx::detail::rpc_internal<upcxx::detail::completions<upcxx::detail::future_cx<upcxx::operation_cx_event, true, upcxx::progress_level::user>>, (lambda at baz.cpp:93:5) &&, bar &>' requested here
    return detail::template rpc_internal<detail::operation_cx_as_future_t, Fn&&, Arg&&...>(
                            ^
baz.cpp:91:10: note: in instantiation of function template specialization 'upcxx::rpc<(lambda at baz.cpp:93:5), bar &>' requested here
  upcxx::rpc(
         ^
3 errors generated.

Comments (3)

  1. Log in to comment