Skip to content

#[derive(IntoBytes)] should ignore unused const arguments #2723

@culebron-ala

Description

@culebron-ala

When deriving IntoBytes, we check to see whether any generics are present:

} else if ast.generics.params.is_empty() {

If they are, we require all fields to be Unaligned:

} else if is_c && !repr.is_align_gt_1() {
// We can't use a padding check since there are generic type arguments.
// Instead, we require all field types to implement `Unaligned`. This
// ensures that the `repr(C)` layout algorithm will not insert any
// padding unless #[repr(align)] explicitly adds padding, which we check
// for in this branch's condition.
//
// FIXME(#10): Support type parameters for non-transparent, non-packed
// structs without requiring `Unaligned`.
(None, true)

This requirement could be lifted if the only generic parameters are const parameters which are not used in the body of the type. This should just be a matter of filtering ast.generics.const_params() and only retaining const params which appear in the type's body. There may be edge cases in which a const param is only used inside of another quantification (e.g. there's a nested const argument that shadows the outer one), but it's fine to conservatively treat these as being equal – it will just result in more types being rejected than should be.

Original text

I have a const generic in a type, and no matter what types I set the inner fields (including a padding field), the derive macro insists that usize, u64, u32, etc. are unaligned. I tried setting a different type for the generic (u8, u16, u32), still the same problem.

use std::path::{Path, PathBuf};
use zerocopy::{FromBytes, Immutable, IntoBytes};

const MERC_SCALE: f64 = 123.456;
const TILE_SIZE: [f64; 20] = [1.; 20];


#[derive(Clone, IntoBytes, FromBytes, Immutable)]
#[repr(C)]
pub struct Tile<const L: usize>(pub u32, pub u32);

impl<const L: usize> Tile<L> {
    pub fn path<P: AsRef<Path>>(&self, prefix: P, extension: &str) -> PathBuf {
        prefix.as_ref().join(L.to_string()).join(self.0.to_string()).join(self.1.to_string()).with_extension(extension)
    }
}

pub fn get_tile<const L: usize>(x: f64, y: f64) -> Tile<L> {
    let tile_size = TILE_SIZE[L];
    Tile(((MERC_SCALE + x) / tile_size) as u32, ((MERC_SCALE - y) / tile_size) as u32)
}

Error:

  |
9 | #[derive(Clone, IntoBytes, FromBytes, Immutable)]
  |                 ^^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `u32`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions