How to write abstraction for reference to object inside host-device unified memory

I am writing a low-level API, which needs to memory allocated by special allocation function.
This memory is accessble by both host and device

Here is my current implementation: (Detail omitted)

/// Marker traits for types that can be on device
/// Implemented for all primitive, non-reference types
pub unsafe trait DeviceCopy: Copy {}
/// Similar to `std::vec::Vec`, but use special memory alloc function
pub struct UnifiedBuffer<T: DeviceCopy> {
    ptr: core::ptr::NonNull<T>,
    len: usize,
}

/// New type for slice, which ensures the slice on unified memory
#[derive(Debug, Copy, Clone)]
pub struct UnifiedSlice<'a, T: DeviceCopy>(&'a [T]);

But the Deref trait implementation confuses me.
It seems no way to Deref from UnifiedBuffer to UnifiedSlice

The compilable code:

impl<T: DeviceCopy> Deref for UnifiedBuffer<T> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
    }
}

What do not work:

impl<'a, T: DeviceCopy> Deref for UnifiedBuffer<T> 
    type Target = UnifiedSlice<'a, T>;

    fn deref(&self) -> &UnifiedSlice<'a, T> {
        todo!();
    }
}

Compilation errors with

the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates

but how to solve it?

It there any special syntax to specify the lifetime?
Or am I writing wrong abstraction?

Alternative ideas:

  1. Declare UnifiedSlice as
pub struct UnifiedSlice<T: DeviceCopy>([T]);

instead of reference type
But I am not sure how to use this?
2. Declare UnifiedPtr as new type of T

pub struct UnifiedPtr<T: DeviceCopy>(T);

and UnifiedBuffer deref to [UnifiedPtr<T>],
but it does not looks like a abstraction for memory address.

Rust Playground

fn main() {
    let buf = UnifiedBuffer { ptr: NonNull::dangling(), len: 0 };
    let a: &UnifiedSlice<u8> = &buf;
    let _: &[u8] = a.as_slice();
    let _: &[u8] = &**a;
    let _: &[u8] = &buf;
}

impl<T: DeviceCopy> UnifiedSlice<T> {
    fn as_slice(&self) -> &[T] {
        &self.0
    }
}

impl<T: DeviceCopy> Deref for UnifiedSlice<T> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        &self.0
    }
}

Do you know how to construct

pub struct UnifiedSlice<T: DeviceCopy>([T])

I don't know. You might want to have a look at slice_dst - Rust

impl<T: DeviceCopy> Deref for UnifiedBuffer<T> {
    type Target = UnifiedSlice<T>;

    fn deref(&self) -> &UnifiedSlice<T> {
        todo!()
    }
}

/// New type for slice, which ensures the slice on unified memory
#[derive(Debug)]
pub struct UnifiedSlice<T: DeviceCopy>([T]);

This compiles. But how to implement the todo part?

Does not seem to be relevant to this question.
I do not think a special crate is needed.

But it tells you how to obtain a [T] in Rust which seems to be what you're asking for.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.