Rfcs: Pod & Packed traits

Created on 12 Oct 2020  路  3Comments  路  Source: rust-lang/rfcs

I'm proposing adding Pod and Packed traits and a write_initialized intrinsic to make it easier to work with structured low-level APIs.

Previous discussions


A sized type T is Pod if any [u8; sizeof(T)] can safely be transmuted to T.

A (possibly unsized) object is Pod if any byte in its object representation can safely be overwritten by any other byte.

All integer types are Pod. All raw pointers to sized types are Pod. Arrays of Pod types are Pod. Tuples, structs and unions which contain only Pod types and which do not have invariants are Pod.


A sized type T is Packed if any object of type T can safely be transmuted to [u8; sizeof(T)].

A (possibly unsized) object is Pod if any byte in its object representation can safely be read as an u8.

All integer types are Packed. All raw pointers on currently supported platforms are Packed. Arrays of of Packed types are Packed. Whether tuples, structs and unions are Packed depends on their contents.

A Packed trait cannot be implemented safely outside the compiler.


Pod and Packed traits make it possible to write safe APIs that are useful in systems programming. For example:

fn pod_zeroed<T: Pod>() -> T;

// Err if sizeof(U) != sizeof(T)
fn pod_read<T: Pod, U: Packed + ?Sized>(u: &U) -> Result<T>;

// Err if sizeof(U) < sizeof(T)
fn pod_read_init<T: Pod, U: Packed + ?Sized>(u: &U) -> Result<T>;

// Err if sizeof(U) is not a multiple of sizeof(T)
fn pod_iter<T: Pod, U: Packed + ?Sized>(u: &U) -> Result<impl Iterator<Item = T>>;

// Err if sizeof(U) != sizeof(T)
fn pod_write<T: Pod + ?Sized, U: Packed + ?Sized>(u: &U, t: &mut MaybeUninit<T>) -> Result<()>;

Pod and Packed do not cover all use cases that deal with transmuting between bytes and objects. For example, it would be useful if the compiler provided the following intrinsic:

/// Overwrites `t` with `u`, replacing all padding bits of `U` by an unspecified bit pattern.
/// Err if sizeof(u) != sizeof(T).
fn write_initialized<T: Pod + ?Sized, U: ?Sized>(u: &U, t: &mut MaybeUninit<T>) -> Result<()>;

This would cover the usecase of writing data structures with padding bytes into memory.


Both Packed and Pod would not be auto-traits. Like Copy, every type has to opt into being Pod or Packed. Like Copy the compiler would verify at compile time that

  • types implementing Pod only contain other Pod types recursively
  • types implementing Packed only contain other Packed types and do not have padding bits

I assume that Packed would be more controversial that Pod due to its platform dependence.

Most helpful comment

You may want to take a look at the safe transmute working group.

All 3 comments

You may want to take a look at the safe transmute working group.

A (possibly unsized) object is Pod if any byte in its object representation can safely be read as an u8.

I guess you mean Packed here?

Yes

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rust-highfive picture rust-highfive  路  75Comments

rust-highfive picture rust-highfive  路  103Comments

rust-highfive picture rust-highfive  路  88Comments

nikomatsakis picture nikomatsakis  路  65Comments

pnkfelix picture pnkfelix  路  160Comments