镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Union cast failed #241

Open
Open

Description

@simensgreen

Expected Behaviour

Can cast [f32; 5] as Data { a: f32, b: [f32; 3], c: f32 }

Example & Steps To Reproduce

#[repr(C)]
#[derive(Clone, Copy)]
struct Data {
    a: f32,
    b: [f32; 3],
    c: f32,
}

union DataOrArray {
    arr: [f32; 5],
    str: Data,
}

impl DataOrArray {
    fn arr(self) -> [f32; 5] { unsafe { self.arr } }
    fn new(arr: [f32; 5]) -> Self { Self { arr } }
}

in shader:

let dora = DataOrArray::new([0.0, 0.0, 0.0, 0.0, 0.0]);
let arr = dora.arr();

Produces:

error: cannot cast between pointer types
         from `*struct types::Data { a: f32, b: [f32; 3], c: f32 }`
           to `*[f32; 5]`

System Info

  • Rust: rustc 1.84.0-nightly (b19329a37 2024-11-21)
  • OS: MacOS 15.3.2
  • GPU: M2 Max
  • rust-gpu: 698f10a

Activity

  1. LegNeato commented on Apr 23, 2025

    @LegNeato
    Collaborator

    Can you try latest master? I landed 2f915a0 which fixed issues with a similar message (#46) and I think this is fixed by it too.

  2. simensgreen commented on Apr 24, 2025

    @simensgreen
    Author

    Nope, even at commit 2f915a0 error still appears

  3. simensgreen commented on Apr 24, 2025

    @simensgreen
    Author

    I tried trick it with core::mem::transmute:

        pub fn arr(self) -> [f32; 5] {
            unsafe { core::mem::transmute(self) }
        }

    Error:

      error: cannot memcpy dynamically sized data
        --> solver/src/types/data_or_array.rs:16:18
         |
      16 |         unsafe { core::mem::transmute(self) }
         |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
    
  4. simensgreen commented on Apr 24, 2025

    @simensgreen
    Author

    I created repo to test this error, but it failed to compile #242

  5. LegNeato commented on Apr 24, 2025

    @LegNeato
    Collaborator

    Ok great, I'll take a look.

  6. LegNeato commented on May 21, 2025

    @LegNeato
    Collaborator

    Wasn't able to find the root cause. This is going to churn shortly with some bigger qptr work so I am hesitant to spend more time until that lands

  7. simensgreen commented on May 25, 2025

    @simensgreen
    Author

    @LegNeato Perhaps I can assist you with the QPTR, but I require further information. Could you please elaborate on what it is and from where it originates?

  8. nazar-pc commented on Jun 25, 2025

    @nazar-pc
    Contributor

    I have a simple example with an array that results in the same error:

    Details
      error: cannot cast between pointer types
             from `*[[u32; 4]; 4]`
               to `*[u32; 16]`
         --> /home/nazar-pc/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/non_null.rs:436:6
          |
      436 |     }
          |      ^
          |
      note: used from within `<core::ptr::non_null::NonNull<[[u32; 4]; 4]>>::cast::<[u32; 16]>`
         --> /home/nazar-pc/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/non_null.rs:436:6
          |
      436 |     }
          |      ^
      note: called by `<ab_proof_of_space_gpu::shaders::chacha8::ChaCha8Block as core::ops::deref::DerefMut>::deref_mut`
         --> src/shaders/chacha8.rs:25:18
          |
      25  |         unsafe { NonNull::from_mut(&mut self.0).cast::<[u32; 16]>().as_mut() }
          |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    Not sure if the root cause is the same, but it looks similar.

    #[repr(C, align(16))]
    pub struct ChaCha8Block(pub [[u32; 4]; 4]);
    
    impl Deref for ChaCha8Block {
        type Target = [u32; 16];
    
        #[inline(always)]
        fn deref(&self) -> &Self::Target {
            // SAFETY: Same size and alignment
            unsafe { NonNull::from_ref(&self.0).cast::<[u32; 16]>().as_ref() }
        }
    }
    
    impl DerefMut for ChaCha8Block {
        #[inline(always)]
        fn deref_mut(&mut self) -> &mut Self::Target {
            // SAFETY: Same size and alignment
            unsafe { NonNull::from_mut(&mut self.0).cast::<[u32; 16]>().as_mut() }
        }
    }

    UPD: Tried #269 in its current state, same issue.

    UPD2: Even simpler piece of code:

    for (d, &initial) in data.iter_mut().zip(&self.data) {
        *d = d.wrapping_add(initial);
    }

    Fails with:

      error: cannot cast between pointer types
             from `*[u32; 16]`
               to `*[u32]`

    Both data and self.data are [u32; 16].

  9. nazar-pc commented on Sep 15, 2025

    @nazar-pc
    Contributor

    This issue is one of the largest contributors of ugly non-idiomatic code in my codebase.

    For example, I have a dynamic index into a fixed size array. This typically means I can use slice operators on an array, but because of this issue it doesn't work:

      error: cannot cast between pointer types
             from `*[struct ManuallyDrop<Match> { value: struct Match { .. } }; 288]`
               to `*[struct ManuallyDrop<Match> { value: struct Match { .. } }]`
         --> src/shader/find_matches_in_buckets.rs:348:35
          |
      348 |             let Some(m) = matches.get_mut(local_matches_offset as usize) else {
          |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    So I have to make explicit bounds check separately and then do array indexing and on top of that hope that compiler will be able to see bounds check and not insert conditional panic on array access (which with rust-gpu I don't have 100% confidence in).

    P.S. No idea where it found ManuallyDrop, I'm using MaybeUninit there instead 🤔

  10. nazar-pc commented on Sep 15, 2025

    @nazar-pc
    Contributor

    I think this is a hard blocker for me for now. I can't really use new types until this is fixed because I need to cast arrays of u32s from shared memory to arrays of use-case specific pointers that are just wrappers over u32 for any type safety.

    Without pointer casting everything is just u32 and it is very difficult to make sense of anything. I can't write sane misuse resistant code like this, it feels more like writing in assembler without types.

  11. nazar-pc commented on Nov 7, 2025

    @nazar-pc
    Contributor

    I eventually ended up with an actual union situation myself, needing it for shared memory reuse between two parts of the fused shader.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions