Skip to content

Union cast failed #241

@simensgreen

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

LegNeato

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.

simensgreen

simensgreen commented on Apr 24, 2025

@simensgreen
Author

Nope, even at commit 2f915a0 error still appears

simensgreen

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) }
     |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
simensgreen

simensgreen commented on Apr 24, 2025

@simensgreen
Author

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

LegNeato

LegNeato commented on Apr 24, 2025

@LegNeato
Collaborator

Ok great, I'll take a look.

LegNeato

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

simensgreen

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?

nazar-pc

nazar-pc commented on Jun 25, 2025

@nazar-pc
Contributor

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

  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].

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

    Participants

    @LegNeato@nazar-pc@simensgreen

    Issue actions

      Union cast failed · Issue #241 · Rust-GPU/rust-gpu