Skip to content

Commit

Permalink
[wip] UnalignUnsized
Browse files Browse the repository at this point in the history
  • Loading branch information
jswrenn committed Nov 26, 2024
1 parent 596521c commit d7f8249
Show file tree
Hide file tree
Showing 11 changed files with 719 additions and 15 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ jobs:
# which a particular feature is supported.
"zerocopy-core-error-1-81-0",
"zerocopy-diagnostic-on-unimplemented-1-78-0",
"zerocopy-unsized-needs-drop-1-63-0",
"zerocopy-generic-bounds-in-const-fn-1-61-0",
"zerocopy-target-has-atomics-1-60-0",
"zerocopy-aarch64-simd-1-59-0",
Expand Down Expand Up @@ -93,6 +94,8 @@ jobs:
features: "--all-features"
- toolchain: "zerocopy-diagnostic-on-unimplemented-1-78-0"
features: "--all-features"
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
features: "--all-features"
- toolchain: "zerocopy-generic-bounds-in-const-fn-1-61-0"
features: "--all-features"
- toolchain: "zerocopy-target-has-atomics-1-60-0"
Expand All @@ -117,6 +120,8 @@ jobs:
toolchain: "zerocopy-core-error-1-81-0"
- crate: "zerocopy-derive"
toolchain: "zerocopy-diagnostic-on-unimplemented-1-78-0"
- crate: "zerocopy-derive"
toolchain: "zerocopy-unsized-needs-drop-1-63-0"
- crate: "zerocopy-derive"
toolchain: "zerocopy-generic-bounds-in-const-fn-1-61-0"
- crate: "zerocopy-derive"
Expand Down Expand Up @@ -212,6 +217,28 @@ jobs:
target: "thumbv6m-none-eabi"
- toolchain: "zerocopy-generic-bounds-in-const-fn-1-61-0"
target: "wasm32-wasi"
# Exclude most targets targets from the
# `zerocopy-unsized-needs-drop-1-63-0` toolchain since the
# `zerocopy-unsized-needs-drop-1-63-0` feature is unrelated to
# compilation target. This only leaves i686 and x86_64 targets.
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
target: "arm-unknown-linux-gnueabi"
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
target: "aarch64-unknown-linux-gnu"
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
target: "powerpc-unknown-linux-gnu"
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
target: "powerpc64-unknown-linux-gnu"
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
target: "riscv64gc-unknown-linux-gnu"
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
target: "s390x-unknown-linux-gnu"
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
target: "x86_64-pc-windows-msvc"
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
target: "thumbv6m-none-eabi"
- toolchain: "zerocopy-unsized-needs-drop-1-63-0"
target: "wasm32-wasi"
# Exclude `thumbv6m-none-eabi` combined with any feature that implies
# the `std` feature since `thumbv6m-none-eabi` does not include a
# pre-compiled std.
Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ zerocopy-core-error-1-81-0 = "1.81.0"
# From 1.78.0, Rust supports the `#[diagnostic::on_unimplemented]` attribute.
zerocopy-diagnostic-on-unimplemented-1-78-0 = "1.78.0"

# From 1.63.0, Rust supports generic types with trait bounds in `const fn`.
zerocopy-unsized-needs-drop-1-63-0 = "1.63.0"

# From 1.61.0, Rust supports generic types with trait bounds in `const fn`.
zerocopy-generic-bounds-in-const-fn-1-61-0 = "1.61.0"

Expand Down
7 changes: 6 additions & 1 deletion src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub(crate) enum MetadataCastError {

impl DstLayout {
/// The minimum possible alignment of a type.
const MIN_ALIGN: NonZeroUsize = match NonZeroUsize::new(1) {
pub(crate) const MIN_ALIGN: NonZeroUsize = match NonZeroUsize::new(1) {
Some(min_align) => min_align,
None => const_unreachable!(),
};
Expand Down Expand Up @@ -598,6 +598,11 @@ impl DstLayout {

Ok((elems, split_at))
}

/// Produces `true` if `self.align` equals 1; otherwise `false`.
pub(crate) const fn is_trivially_aligned(&self) -> bool {
matches!(self.align, DstLayout::MIN_ALIGN)
}
}

// TODO(#67): For some reason, on our MSRV toolchain, this `allow` isn't
Expand Down
46 changes: 46 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,24 @@ pub unsafe trait KnownLayout {
#[doc(hidden)]
const LAYOUT: DstLayout;

/// Does `Self` have a non-trivial destructor?
///
/// This defaulted implementation is appropriate for all types except
/// `UnalignUnsized<T>` which has an explicit `Drop` implementation and is
/// thus unconditionally `mem::needs_drop`, even if `T` is not
/// `mem::needs_drop`.
///
/// # Safety
///
/// Unsafe code may not assume anything about the value of `NEEDS_DROP`.
const NEEDS_DROP: bool = {
#[cfg(zerocopy_unsized_needs_drop_1_63_0)]
let val = core::mem::needs_drop::<Self>();
#[cfg(not(zerocopy_unsized_needs_drop_1_63_0))]
let val = true;
val
};

/// SAFETY: The returned pointer has the same address and provenance as
/// `bytes`. If `Self` is a DST, the returned pointer's referent has `elems`
/// elements in its trailing slice.
Expand Down Expand Up @@ -797,6 +815,34 @@ pub unsafe trait KnownLayout {
// resulting size would not fit in a `usize`.
meta.size_for_metadata(Self::LAYOUT)
}

/// Run the destructor of `ptr`'s referent.
///
/// # Panics
///
/// Implementations of this function never panic.
///
/// # Compile-Time Assertions
///
/// Implementations of this function must emit a post-monomorphization error
/// if `ptr`'s referent has a non-trivial drop that cannot be run.
///
/// # Safety
///
/// This function may only be called from the destructor (i.e.,
/// `Drop::drop`) of transitive owner of `ptr`'s referent. After invoking
/// this function, it is forbidden to re-use `ptr` or its referent.
#[doc(hidden)]
#[inline]
unsafe fn destroy(ptr: MaybeAligned<'_, Self, invariant::Exclusive>) {
// SAFETY: The preconditions of `destroy_unsized` are identical to that
// of `destroy` and are ensured by the caller.
//
// This defaulted implementation works for all types, but for sized
// types, delegating to `crate::util::destroy::destroy_sized` — which
// does not allocate — is preferable.
unsafe { crate::util::destroy::destroy_unsized(ptr) }
}
}

/// The metadata associated with a [`KnownLayout`] type.
Expand Down
22 changes: 22 additions & 0 deletions src/pointer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,28 @@ where
unsafe { core::ptr::read_unaligned(raw) }
}

/// Reads the value from `MaybeAligned`.
///
/// # Safety
///
/// If `T` has a non-trivial destructor, using the returned `T` (including
/// dropping it) and the original referent may cause undefined behavior. The
/// caller ensures this does not occur.
#[must_use]
#[inline]
pub(crate) unsafe fn read_unaligned_unchecked<R>(self) -> T
where
R: AliasingSafeReason,
T: AliasingSafe<T, Aliasing, R> + Sized,
{
let raw = self.as_non_null().as_ptr();
// SAFETY: By invariant on `MaybeAligned`, `raw` contains
// validly-initialized data for `T`. By `T: AliasingSafe`, we are
// permitted to perform a read of `raw`'s referent. The caller ensures
// that subsequent uses of `T` do not induce UB.
unsafe { core::ptr::read_unaligned(raw) }
}

/// Views the value as an aligned reference.
///
/// This is only available if `T` is [`Unaligned`].
Expand Down
Loading

0 comments on commit d7f8249

Please sign in to comment.