cxx
cxx copied to clipboard
Prevent emitting const const on C++ codegen when using a Slice with a reference
Fixes https://github.com/dtolnay/cxx/issues/830
It seems that a container cannot hold references either: https://stackoverflow.com/questions/1155142/why-do-i-get-an-error-in-forming-reference-to-reference-type-map, instead one should wrap a reference around std::reference_wrapper, however, I don't know how to extend Slice to convert a reference into a reference_wrapper
Maybe with a partial template specialization in cxx.h which applies to instantiations of rust::Slice<T &>?
template <typename T>
class Slice<T &> final {
/* uses reference_wrapper internally for this specialization */
};
Alternatively it's possible we can fix this purely by using the existing partial specialized helpers that already exist in <type_traits>. For example instead of:
https://github.com/dtolnay/cxx/blob/064cf12b7850e4a3e2e09134eeea8fc619e60792/include/cxx.h#L170
we'd have:
- T &operator[](std::size_t n) const noexcept;
+ std::add_lvalue_reference<T>::type operator[](std::size_t n) const noexcept;
According to https://en.cppreference.com/w/cpp/types/add_reference that has the semantics we want.
If
Tis a function type that has no cv- or ref- qualifier or an object type, provides a member typedeftypewhich isT&. IfTis an rvalue reference to some typeU, thentypeisU&. Otherwise,typeisT.
In other words rust::Slice<const Struct>::operator[] would return const Struct &, whereas rust::Slice<const Struct &>::operator[] would also return const Struct &, because add_lvalue_reference is instantiated with a type that is already a reference.
In other words rust::Slice<const Struct>::operator[] would return const Struct &, whereas rust::Slice<const Struct &>::operator[] would also return const Struct &, because add_lvalue_reference is instantiated with a type that is already a reference.
Sounds like it would fix the issue, let me update the PR!
I think it is necessary to update the generated cxx.cc file to consider add_lvalue_reference
error: no declaration matches ‘T& rust::cxxbridge1::Slice<T>::operator[](std::size_t) const
Do you know where I should do the corresponding modifications?
I tried this change locally, and it seems to work, although I have to use std::reference_wrapper on the signature
match &slice.inner {
Type::Ref(r) => {
// let inner_ref = r.inner;
write!(out, "std::reference_wrapper<");
write_type(out, &r.inner);
write!(out, ">");
}
_ => {
write!(out, "const ");
write_type(out, &slice.inner);
}
}
std::shared_ptr<CrossTensor> index(
const std::shared_ptr<CrossTensor> &tensor,
rust::Slice<std::reference_wrapper<CrossTensorRef>> indices);
@dtolnay, do you prefer using std::reference_wrapper here?
Any chance of this being merged? I ran into the issue described in #830 so having a fix would be nice. I'd be happy to help out if some work is needed to get it done :)