-
Notifications
You must be signed in to change notification settings - Fork 365
Expose a way to bypass is_trivially_destructible/_move_constructible check on extern types passed by value #359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Proof of concept: #include <iostream>
#include <string>
#include <type_traits>
namespace rust {
namespace detail {
template <typename... Ts> struct make_void { using type = void; };
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
template <typename Void, template <typename...> class, typename...>
struct detect : std::false_type {};
template <template <typename...> class T, typename... A>
struct detect<void_t<T<A...>>, T, A...> : std::true_type {};
template <template <typename...> class T, typename... A>
using is_detected = detect<void, T, A...>;
template <typename T> using detect_IsRelocatable = typename T::IsRelocatable;
template <typename T>
struct get_IsRelocatable
: std::is_same<typename T::IsRelocatable, std::true_type> {};
} // namespace detail
template <typename T>
struct IsRelocatable
: std::conditional<
detail::is_detected<detail::detect_IsRelocatable, T>::value,
detail::get_IsRelocatable<T>,
std::integral_constant<
bool, std::is_trivially_move_constructible<T>::value &&
std::is_trivially_destructible<T>::value>>::type {};
} // namespace rust
struct O { int32_t x; };
struct P { std::string s; };
struct Q; template <> struct rust::IsRelocatable<Q> : std::true_type {};
struct R { ~R(); };
struct S { ~S(); using IsRelocatable = std::true_type; };
int main() {
std::cout << rust::IsRelocatable<O>::value << std::endl;
std::cout << rust::IsRelocatable<P>::value << std::endl;
std::cout << rust::IsRelocatable<Q>::value << std::endl;
std::cout << rust::IsRelocatable<R>::value << std::endl;
std::cout << rust::IsRelocatable<S>::value << std::endl;
} |
I tested this code, and this could be an issue for this use case: struct ImplCopy {
int32_t x;
ImplCopy(const ImplCopy &obj): x(obj.x) {}
};
std::cout << rust::IsRelocatable<ImplCopy>::value << std::endl; // returns 0 As far as I can tell, this should still be a trivial move in this specific case, but isn't because of the copy constructor. |
That is the intended behavior!
Letting Rust move one of them around with no constructor call would defeat this. class CapabilityLog {
friend struct ImplCopy;
static std::vector<std::tuple<const ImplCopy*, const ImplCopy*>> log_;
};
struct ImplCopy {
int32_t x;
ImplCopy(const ImplCopy &obj) {
CapabilityLog::log_.emplace_back(&obj, this);
}
}; The opt out required in the proof of concept (#359 (comment)) is: // if you own the type
struct ImplCopy {
int32_t x;
ImplCopy(const ImplCopy &obj);
+ using IsRelocatable = std::true_type;
}; // otherwise
+ template <> struct rust::IsRelocatable<ImplCopy> : std::true_type {}; |
As discussed in #339.
The text was updated successfully, but these errors were encountered: