Flat Slice from Box<[[T; H]; W]>

I have a struct Array2d(Box<[[T; H]; W]>) and a trait Storage. The Storage trait contains some functions I need for my project. Now I want a fast way to iterate over all elements where I don't care about any ordering in the Array2d.
I thought it would be easiest to do it by using slices with two functions:
fn flat_slice(&self) -> &[Self::Atom]; and fn flat_slice_mut(&mut self) -> &mut [Self::Atom];
I'm new to unsafe but thought this would be the easiest way to implement this function through std::slice::from_raw_parts and std::slice::from_raw_parts_mut respectively.

    fn flat_slice(&self) -> &[Self::Item] {
        let len = W * H * std::mem::size_of::<Self::Item>();
        let ptr: *const Self::Item = &(*self.0)[0][0];
        unsafe { std::slice::from_raw_parts(ptr, len) }
    }

Two Questions:

  1. Did I get the raw pointer to the first element correctly? (I'm confused about the Box)
  2. Is this safe?

Thanks!

You don't have to multiply the length with size_of::<Item>(), as the documentation clearly indicates.

Other than that, this is just <[_]>::flatten(). Looking at its implementation, it seems like you are not handling ZSTs correctly. The explicit deref, the parentheses, and the whole indexing business are unnecessary.

Actually, doing this via indexing is incorrect, because of provenance. The reference to self.0[0][0] only points to the first element, and you are not allowed to use it for accessing any other element, even though it has the same numerical address as the slice itself.

You should just use slice::as_ptr(), like this.

4 Likes

It's unsound:

error: Undefined Behavior: trying to retag from <2913> for SharedReadOnly permission at alloc1522[0x4], but that tag does not exist in the borrow stack for this location
   --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/raw.rs:100:9
    |
100 |         &*ptr::slice_from_raw_parts(data, len)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |         |
    |         trying to retag from <2913> for SharedReadOnly permission at alloc1522[0x4], but that tag does not exist in the borrow stack for this location
    |         this error occurs as part of retag at alloc1522[0x0..0x18]
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <2913> was created by a SharedReadOnly retag at offsets [0x0..0x4]
   --> src/main.rs:3:25
    |
3   |     let ptr: *const T = &s[0][0];
    |                         ^^^^^^^^

Note: nightly Rust has slice::flatten and Vec::into_flattened.

And you can imitate : Rust Playground

2 Likes

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.