Repository: kokkos/kokkos (2026-03-12T22:53:04Z)

Issue:
Create an unmanaged subview from a view is broken (rank-1)
Creating an unmanaged subview of a view as follows used to work until 8cfdfd8abe48b57cfb1b887fd8c9e3d77f990b51 from @crtrott :
```c++
TEST(TEST_CATEGORY, unmanaged_subview_from_view_is_broken) {
  using memory_space = typename TEST_EXECSPACE::memory_space;
  using view_t    = Kokkos::View<double*, memory_space>;
  using view_um_t = Kokkos::View<double*, memory_space, Kokkos::MemoryTraits<Kokkos::Unmanaged>>;

  constexpr size_t size = 10;
  constexpr Kokkos::pair<size_t, size_t> range {0, 5};

  const view_t values("values", size);

  const view_um_t subview_from_view(values       , range); // Does not compile...
  const view_um_t subview_from_raw (values.data(), range.second); // OK !
}
```

Reverting 8cfdfd8abe48b57cfb1b887fd8c9e3d77f990b51 makes the above code compile just fine. The question is, since there wasn't any test that captured the regression:
> Is it allowed to create an unmanaged view from a view as done above?

If so, this needs a fix @crtrott :wink: 

Compiler output:
```bash
In file included from /workspaces/kokkos/core/src/Kokkos_View.hpp:15,
                 from /workspaces/kokkos/core/src/Kokkos_Parallel.hpp:18,
                 from /workspaces/kokkos/core/src/OpenMP/Kokkos_OpenMP.hpp:19,
                 from /workspaces/kokkos/core/src/decl/Kokkos_Declare_OPENMP.hpp:8,
                 from /workspaces/kokkos/build-with-gcc-OpenMP/KokkosCore_Config_DeclareBackend.hpp:7,
                 from /workspaces/kokkos/core/src/Kokkos_Core.hpp:32,
                 from /workspaces/kokkos/core/unit_test/TestGraph.hpp:8,
                 from /workspaces/kokkos/build-with-gcc-OpenMP/core/unit_test/openmp/TestOpenMP_Graph.cpp:2:
/workspaces/kokkos/core/src/View/Kokkos_BasicView.hpp: In instantiation of 'Kokkos::Impl::BV::BasicView<ElementType, Extents, LayoutPolicy, AccessorPolicy>::BasicView(Kokkos::Impl::SubViewCtorTag, const Kokkos::Impl::BV::BasicView<OtherT, OtherE, OtherL, OtherA>&, SliceSpecifiers ...) [with OtherElementType = double; OtherExtents = Kokkos::extents<long unsigned int, 18446744073709551615>; OtherLayoutPolicy = Kokkos::Experimental::layout_right_padded<18446744073709551615>; OtherAccessorPolicy = Kokkos::Impl::SpaceAwareAccessor<Kokkos::HostSpace, Kokkos::Impl::ReferenceCountedAccessor<double, Kokkos::HostSpace, Kokkos::default_accessor<double> > >; SliceSpecifiers = {Kokkos::pair<long unsigned int, long unsigned int>}; ElementType = double; Extents = Kokkos::extents<long unsigned int, 18446744073709551615>; LayoutPolicy = Kokkos::Experimental::layout_right_padded<18446744073709551615>; AccessorPolicy = Kokkos::Impl::SpaceAwareAccessor<Kokkos::HostSpace, Kokkos::default_accessor<double> >]':
/workspaces/kokkos/core/src/Kokkos_View.hpp:846:63:   required from 'Kokkos::View<DataType, Properties>::View(const Kokkos::View<RT, RP ...>&, Arg0, Args ...) [with RT = double*; RP = {Kokkos::HostSpace}; Arg0 = Kokkos::pair<long unsigned int, long unsigned int>; Args = {}; DataType = double*; Properties = {Kokkos::HostSpace, Kokkos::MemoryTraits<1>}]'
  846 |       : base_t(Impl::subview_ctor_tag, src_view, arg0, args...) {}
      |                                                               ^
/workspaces/kokkos/core/unit_test/TestGraph.hpp:1472:57:   required from here
 1472 |   const view_um_t subview_from_view(values       , range); // Does not compile
      |                                                         ^
/workspaces/kokkos/core/src/View/Kokkos_BasicView.hpp:600:34: error: cannot convert 'Kokkos::Impl::SpaceAwareAccessor<Kokkos::HostSpace, Kokkos::Impl::ReferenceCountedAccessor<double, Kokkos::HostSpace, Kokkos::default_accessor<double> > >::data_handle_type' {aka 'Kokkos::Impl::ReferenceCountedDataHandle<double, Kokkos::HostSpace>'} to 'Kokkos::Impl::BV::BasicView<double, Kokkos::extents<long unsigned int, 18446744073709551615>, Kokkos::Experimental::layout_right_padded<18446744073709551615>, Kokkos::Impl::SpaceAwareAccessor<Kokkos::HostSpace, Kokkos::default_accessor<double> > >::data_handle_type' {aka 'double*'} in assignment
  600 |     m_ptr = src_view.m_acc.offset(src_view.m_ptr, sub_mapping_result.offset);
      |             ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                  |
      |                                  Kokkos::Impl::SpaceAwareAccessor<Kokkos::HostSpace, Kokkos::Impl::ReferenceCountedAccessor<double, Kokkos::HostSpace, Kokkos::default_accessor<double> > >::data_handle_type {aka Kokkos::Impl::ReferenceCountedDataHandle<double, Kokkos::HostSpace>}
In file included from /workspaces/kokkos/core/src/View/Kokkos_ViewTraits.hpp:19,
                 from /workspaces/kokkos/core/src/View/Kokkos_BasicView.hpp:18:
/workspaces/kokkos/core/src/View/MDSpan/Kokkos_MDSpan_Accessor.hpp:304:12: note: explicit conversion function was not considered
  304 |   explicit operator pointer() const noexcept { return m_handle; }
      |            ^~~~~~~~
```


Discussion:
Just noting that this compiles in 5.0.1 and does not in 5.02 (since we had backported #8822)
Yeah agree the is a bug. I suspect we might just need a static cast on that line 600?
> Yeah agree the is a bug. I suspect we might just need a static cast on that line 600?

Yeah
```diff
diff --git a/core/src/View/Kokkos_BasicView.hpp b/core/src/View/Kokkos_BasicView.hpp
index a67ce315d..525676b93 100644
--- a/core/src/View/Kokkos_BasicView.hpp
+++ b/core/src/View/Kokkos_BasicView.hpp
@@ -597,7 +597,7 @@ class BasicView {
     // Explicit cast is needed because submdspan_mapping may return a different
     // layout type.
     using sub_accessor_t = typename OtherAccessorPolicy::offset_policy;
-    m_ptr = src_view.m_acc.offset(src_view.m_ptr, sub_mapping_result.offset);
+    m_ptr = static_cast<data_handle_type>(src_view.m_acc.offset(src_view.m_ptr, sub_mapping_result.offset));
     m_map = mapping_type(sub_mapping_result.mapping);
     m_acc = sub_accessor_t(src_view.m_acc);
```
would fix it.



Patch:
diff --git a/core/src/View/Kokkos_BasicView.hpp b/core/src/View/Kokkos_BasicView.hpp
index a67ce315d35..65c659364e8 100644
--- a/core/src/View/Kokkos_BasicView.hpp
+++ b/core/src/View/Kokkos_BasicView.hpp
@@ -597,7 +597,8 @@ class BasicView {
     // Explicit cast is needed because submdspan_mapping may return a different
     // layout type.
     using sub_accessor_t = typename OtherAccessorPolicy::offset_policy;
-    m_ptr = src_view.m_acc.offset(src_view.m_ptr, sub_mapping_result.offset);
+    m_ptr                = static_cast<data_handle_type>(
+        src_view.m_acc.offset(src_view.m_ptr, sub_mapping_result.offset));
     m_map = mapping_type(sub_mapping_result.mapping);
     m_acc = sub_accessor_t(src_view.m_acc);
 


Test patch:
diff --git a/core/unit_test/CMakeLists.txt b/core/unit_test/CMakeLists.txt
index d6539dc9daa..0ec1d3cccee 100644
--- a/core/unit_test/CMakeLists.txt
+++ b/core/unit_test/CMakeLists.txt
@@ -299,7 +299,16 @@ foreach(Tag Threads;Serial;OpenMP;Cuda;HPX;OpenACC;HIP;SYCL)
     endforeach()
 
     set(${Tag}_SOURCES2D)
-    foreach(Name SubView_c10 SubView_c11 SubView_c12 SubView_c13 SubView_c14 SubView_c15)
+    foreach(
+      Name
+      SubView_c10
+      SubView_c11
+      SubView_c12
+      SubView_c13
+      SubView_c14
+      SubView_c15
+      SubView_c16
+    )
       set(file ${dir}/Test${Tag}_${Name}.cpp)
       # Write to a temporary intermediate file and call configure_file to avoid
       # updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
diff --git a/core/unit_test/TestSubView_c15.hpp b/core/unit_test/TestSubView_c15.hpp
index 6718e40ff5b..b51a4f18069 100644
--- a/core/unit_test/TestSubView_c15.hpp
+++ b/core/unit_test/TestSubView_c15.hpp
@@ -27,7 +27,7 @@ TEST(TEST_CATEGORY_DEATH, view_subview_constructor_layout_compatibility) {
     (void)Kokkos::View<int*, LS>(a1, Kokkos::ALL, 1);
 
     // FIXME: This doesn't compile for BasicView, but should
-    //(void)Kokkos::View<int*, LR>(a, Kokkos::ALL, 1);
+    // (void)Kokkos::View<int*, LR>(a1, Kokkos::ALL, 1);
   }
   {
     // Using subview dims (1, ALL). For a LayoutLeft,
diff --git a/core/unit_test/TestSubView_c16.hpp b/core/unit_test/TestSubView_c16.hpp
new file mode 100644
index 00000000000..711123cdb5f
--- /dev/null
+++ b/core/unit_test/TestSubView_c16.hpp
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+// SPDX-FileCopyrightText: Copyright Contributors to the Kokkos project
+
+#include <gtest/gtest.h>
+#include <Kokkos_Macros.hpp>
+#ifdef KOKKOS_ENABLE_EXPERIMENTAL_CXX20_MODULES
+import kokkos.core;
+#else
+#include <Kokkos_Core.hpp>
+#endif
+
+namespace {
+// Test that the subview constructor works for constructing subviews from
+// Views where one of them has the Kokkos::Unmanaged memory trait
+TEST(TEST_CATEGORY, view_create_unmanaged_subview_from_managed) {
+  int N    = 10;
+  using LR = Kokkos::LayoutRight;
+  using LL = Kokkos::LayoutLeft;
+  using LS = Kokkos::LayoutStride;
+
+  Kokkos::View<int**, LL> a1("A1", N, N);
+  Kokkos::View<int**, LL, Kokkos::MemoryTraits<Kokkos::Unmanaged>> a1_unmanaged(
+      a1.data(), N, N);
+  {
+    // Using subview dims (ALL, 1). For a LayoutLeft,
+    // any subview layout should be appropriate.
+    (void)Kokkos::View<int*, LL, Kokkos::MemoryTraits<Kokkos::Unmanaged>>(
+        a1, Kokkos::ALL, 1);
+    (void)Kokkos::View<int*, LS, Kokkos::MemoryTraits<Kokkos::Unmanaged>>(
+        a1, Kokkos::ALL, 1);
+
+    (void)Kokkos::View<int*, LL>(a1_unmanaged, Kokkos::ALL, 1);
+    (void)Kokkos::View<int*, LS>(a1_unmanaged, Kokkos::ALL, 1);
+    // FIXME: This doesn't compile for BasicView, but should
+    // (void)Kokkos::View<int*, LR>(a1_unmanaged, Kokkos::ALL, 1);
+  }
+
+  Kokkos::View<int**, LL> a2("A2", 1, N);
+  Kokkos::View<int**, LL, Kokkos::MemoryTraits<Kokkos::Unmanaged>> a2_unmanaged(
+      a2.data(), 1, N);
+  {
+    // Using subview dims (0, ALL). Any subview layout should be appropriate.
+    (void)Kokkos::View<int*, LL, Kokkos::MemoryTraits<Kokkos::Unmanaged>>(
+        a2, 0, Kokkos::ALL);
+    (void)Kokkos::View<int*, LS, Kokkos::MemoryTraits<Kokkos::Unmanaged>>(
+        a2, 0, Kokkos::ALL);
+    (void)Kokkos::View<int*, LR, Kokkos::MemoryTraits<Kokkos::Unmanaged>>(
+        a2, 0, Kokkos::ALL);
+
+    (void)Kokkos::View<int*, LL>(a2_unmanaged, 0, Kokkos::ALL);
+    (void)Kokkos::View<int*, LS>(a2_unmanaged, 0, Kokkos::ALL);
+    (void)Kokkos::View<int*, LR>(a2_unmanaged, 0, Kokkos::ALL);
+  }
+}
+}  // namespace