Skip to content

ACP: Trait for types that can be safely initialized with all-zero byte pattern #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jmillikin opened this issue Sep 17, 2022 · 2 comments
Labels
api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api

Comments

@jmillikin
Copy link

Proposal

Problem statement

When working with FFI it's common to have large structs full of integers. In C/C++ these are idiomatically initialized to all-zero with memset. In Rust, the equivalent requires unsafe with unsafe { core::mem::zeroed() }. The Rust version also requires the programmer to verify that all fields are safe to zero-initialize, which is not true of some patterns such as "struct full of function pointers as pseudo-vtable" .

Motivation, use-cases

Given a struct like the following (used for calling Linux's statx syscall):

#[repr(C)]
pub struct statx {
	pub stx_mask: u32,
	pub stx_blksize: u32,
	pub stx_attributes: u64,
	pub stx_nlink: u32,
	pub stx_uid: u32,
	pub stx_gid: u32,
	pub stx_mode: u16,
	_pad1: [u16; 1],
	pub stx_ino: u64,
	pub stx_size: u64,
	pub stx_blocks: u64,
	pub stx_attributes_mask: u64,
	pub stx_atime: statx_timestamp,
	pub stx_btime: statx_timestamp,
	pub stx_ctime: statx_timestamp,
	pub stx_mtime: statx_timestamp,
	pub stx_rdev_major: u32,
	pub stx_rdev_minor: u32,
	pub stx_dev_major: u32,
	pub stx_dev_minor: u32,
	_pad2: [u64; 14],
}

#[repr(C)]
pub struct statx_timestamp {
	pub tv_sec: i64,
	pub tv_nsec: u32,
	_pad: i32,
}

Without using unsafe initialization is less performant, and also an absolute giant pain because of all the fields. There's also increased maintenance overhead as the unused padding fields are filled in by upstream projects.

However, this is pretty much the perfect case for a struct that is safe to initialize with an all-zero byte pattern via core::mem::zeroed. It's also possible for the compiler to recognize this is safe, since it knows that (1) plain integers are safe to zero-initialize and (2) the struct (recursively) contains only plain integers.

Solution sketches

If there was a trait that could be derived to indicate "this struct is safe to initialize with zeros", then the compiler could verify the safety, and the programmer could use safe code to initialize it.

Rough example:

#[derive(ZeroInit)]
pub struct just_ints {
  a: bool,
  b: i32,
  c: u64,
  d: [u64; 4],
  e: char,
  f: f32,
}

impl just_ints {
  pub fn new() -> Self { ZeroInit::zero_init() }
}

Compilation would fail if the safety can't be proven:

// all of these cases fail to compile

#[derive(ZeroInit)]
struct not_zero_init_safe_1 {
  a: Option<u32>,
}

#[derive(ZeroInit)]
struct not_zero_init_safe_2 {
  a: &'static u32,
}

#[derive(ZeroInit)]
struct not_zero_init_safe_3 {
  a: *const u32,
}

#[derive(ZeroInit)]
struct not_zero_init_safe_4 {
  a: fn() -> u32,
}

#[derive(ZeroInit)]
struct not_zero_init_safe_5 {
  a: (u32, u32),
}

Links and related work

https://internals.rust-lang.org/t/request-iszero-trait-and-derive-iszero/12636/14 (similar name, different semantics)

rust-lang/rust#60978

What happens now?

This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.

@jmillikin jmillikin added api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api labels Sep 17, 2022
@thomcc
Copy link
Member

thomcc commented Sep 17, 2022

I think this possibly needs more than ACP, probably RFC. It runs up against lang-team concerns, like safe transmute and related efforts.

@jmillikin
Copy link
Author

OK, that's fair.

@jmillikin jmillikin closed this as not planned Won't fix, can't repro, duplicate, stale Sep 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api
Projects
None yet
Development

No branches or pull requests

2 participants