Feature proposal: Layout gadgets.
- Dominant language
- Rust
- Stars
- 2.6k
- Forks
- 179
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 29
Description
*Any design for this issue will interact with other issues tracked by #885; make sure to read that issue when tackling this one.*
When writing low-level code, it is often vital to specify that a type satisfies some particular alignment. In Rust, this is achieved with by annotating the type with `#[repr(align(N))]`, where `N` is the desired minimum alignment. Similarly, the maximum alignment of a type can be constrained with `#[repr(packed(N))]`. Unfortunately, these `N`s **must** be provided as integer literals; an expression cannot be provided. Consequently, one must duplicate the definition of a structure for different alignments, and one must jump through hoops to specify computed alignments. Zerocopy could provide the machinery for doing this, so others do not need to re-invent it.
## Potential Gadgets
### `Align`
Concretely, zerocopy will provide a zero-sized `Align` type:
```rust
#[repr(transparent)]
pub struct Align(/* implementation details */)
where
Self: Aligned;
impl Align
where
Self: Aligned;
{
pub const fn new() -> Self {
/* implementation details */
}
}
```
...and a trait `Aligned` that bounds `N` to be valid alignments (i.e., powers of two ≤ 228).
These items can then be used by programmers to `const`-specify the minimum alignments of their own types, by placing `Align` as the first field; e.g.:
```rust
use zerocopy::layout::{Align, Aligned};
use core::mem::align_of;
#[repr(C)]
struct Foo
where
Align: Aligned
{
_align: Align,
bar: u8,
baz: u16,
}
assert_eq!(align_of::>(), 2);
assert_eq!(align_of::>(), 2);
assert_eq!(align_of::>(), 4);
```
### `MinAlign`
Inverting the above pattern, the wrapper `MinAlign` aligns `T` to at least `N`:
```rust
#[repr(C)]
pub struct MinAlign(Align, T)
where
Align: Aligned;
```
This wrapper covers the common case of using `Align` to increase the alignment of a type, without requiring that the type's definition is modified.
### `MinSizeAlign`
It's occasionally useful to specify both a minimum alignment *and* size of an allocation. We can provide such a wrapper like so:
```rust
#[repr(C)]
pub union MinSizeAlign
where
Align: Aligned,
{
aligned: ManuallyDrop>,
_min_size: [MaybeUninit; MIN_SIZE],
}
```
This gadget would be useful, for instance, in our ongoing experiments with `KnownLayout`, in which a constant allocation of minimum alignment and size must be produced.
### `MaxAlign`?
For completeness, we *could* define a `MaxAlign` wrapper. However, I believe the use of such a wrapper is sufficiently (1) niche and (2) footgun-y that we shouldn't define it.
## Prior Art
The `Align` gadget is also provided by the [elain](https://crates.io/crates/elain). I maintain this crate, but would like to deprecate it. I believe that the safety-minded folks who might need such a gadget are also unlikely to take a dependency on a small, single-purpose crate like `elain`. Its functionality would be better suited here, in zerocopy, since any code relying on such layout gadgets is almost certainly doing unsafe things with them.
## Unresolved Questions
- Should these items be defined in an enclosing module?
- What should the name of `MinAlign` be? Is that name suitable, or would `AlignTo` be more descriptive?
Contributor guide
Assessment
This issue has not been assessed yet.