shame icon indicating copy to clipboard operation
shame copied to clipboard

`sm::CpuAligned` not implemented for `!Sized + sm::CpuLayout` structs

Open RayMarch opened this issue 9 months ago • 1 comments

the trait sm::CpuAligned is not public and not implemented for !Sized + sm::CpuLayout structs.

as of now, the following code doesn't compile

#[derive(sm::CpuLayout)]
#[repr(C)]
struct Unsized {
    a: f32,
    b: [f32],
}
< Unsized as sm::CpuAligned>::CPU_ALIGNMENT;

Solution:

  • add sm::CpuAligned to the public interface.
  • add an impl block for sm::CpuAligned in the #[derive(sm::CpuLayout)] macro that takes the same bounds as the impl block for sm::CpuLayout and infers the alignment and optional size from the fields.

RayMarch avatar May 07 '25 13:05 RayMarch

implementing sm::CpuAligned in the derive macro causes overlapping implementations with the blanket std::marker::Sized implementation

this is the code used:

impl<#generics_decl> #re::CpuAligned for #derive_struct_ident<#(#idents_of_generics),*> 
where
#(#first_fields_type: ::std::marker::Sized,)*
#(#field_type: #re::CpuAligned,)*
#where_clause_predicates {
    const CPU_ALIGNMENT: usize = {
        use #re::CpuAligned;
        let mut max_align = <#last_field_type>::CPU_ALIGNMENT;
        #({
            let field_align = <#first_fields_type>::CPU_ALIGNMENT;
            if field_align > max_align {
                max_align = field_align;
            }
        })*
        max_align
    };
    const CPU_SIZE: Option<usize> = {
        use std::alloc::Layout;
        let mut layout = Layout::from_size_align(0, 1)
            .expect("taken directly from official docs");
        #(
            layout = layout.extend(Layout::new::<#first_fields_type>())
                .expect("compile time layout overflow").0;
        )*
        match <#last_field_type>::CPU_SIZE {
            None => None,
            Some(last_size) => {
                let last_align = <#last_field_type>::CPU_ALIGNMENT;
                let last_field_layout = Layout::from_size_align(last_size, last_align)
                    .expect("compile time invalid layout");
                let layout = layout.extend(last_field_layout)
                    .expect("compile time layout overflow").0;
                layout.pad_to_align(); 
                Some(layout.size())
            },
        }
    };
    fn alignment() -> usize {
        Self::CPU_ALIGNMENT
    }
}

Progress on this issue might require merging sm::CpuAligned with sm::CpuLayout.

RayMarch avatar May 07 '25 17:05 RayMarch