Hello.
I've been bitten a few times when passing the result of submdspan() to a function that expects a standard mdspan.
By default, mdspan uses layout_right, whereas submdspan() may return a layout_right_padded when the underlying data is non-contiguous. This is expected, but the result can be implicitly converted to layout_right, which may lead to undefined behavior if left unnoticed.
#include <mdspan/mdspan.hpp>
#include <vector>
#include <gtest/gtest.h>
TEST(TestImplicitLayoutConversion, conversion_from_right_padded)
{
std::vector<int> data(3 * 3);
for (size_t i = 0; i < data.size(); ++i)
data[i] = int(i);
// This is a `layout_right` of extent 3x3.
Kokkos::mdspan<int, Kokkos::dextents<size_t, 2>> good(data.data(), 3, 3);
// This is a `layout_right_padded` of extent 3x2 (non contiguous).
auto sub = Kokkos::submdspan(good, Kokkos::full_extent, std::tuple{0, 2});
// This is a `layout_right` of extent 3x2 (wrongly assumed contiguous).
Kokkos::mdspan<int, Kokkos::dextents<size_t, 2>> bad = sub;
// This passes, as expected.
ASSERT_EQ((MDSPAN_IMPL_OP(bad, 0, 1)), (MDSPAN_IMPL_OP(sub, 0, 1)));
// This fails: `bad(1, 1)` accesses `data[2*1 + 1]` instead of `data[3*1 + 1]`.
ASSERT_EQ((MDSPAN_IMPL_OP(bad, 1, 1)), (MDSPAN_IMPL_OP(sub, 1, 1)));
}
The above test exhibits wrong memory access due to the implicit conversion. I'd argue it shouldn't even compile at all.
Hello.
I've been bitten a few times when passing the result of
submdspan()to a function that expects a standardmdspan.By default,
mdspanuseslayout_right, whereassubmdspan()may return alayout_right_paddedwhen the underlying data is non-contiguous. This is expected, but the result can be implicitly converted tolayout_right, which may lead to undefined behavior if left unnoticed.The above test exhibits wrong memory access due to the implicit conversion. I'd argue it shouldn't even compile at all.