| #!/usr/bin/env bash | ||
| # | ||
| # Copyright 2026 The Fuchsia Authors | ||
| # | ||
| # Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 | ||
| # <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT | ||
| # license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. | ||
| # This file may not be copied, modified, or distributed except according to | ||
| # those terms. | ||
| set -e | ||
| if [ $# -ne 1 ]; then | ||
| echo "Usage: $0 <version>" >&2 | ||
| exit 1 | ||
| fi | ||
| VERSION="$1" | ||
| # Update the package version in the Anneal crate's manifest. This is the | ||
| # authoritative version for the crate. | ||
| sed -i -e "s/^version = \"[0-9a-zA-Z\.-]*\"/version = \"$VERSION\"/" anneal/Cargo.toml | ||
| # Update the installation instructions in the README to reflect the new version. | ||
| # This ensures that users copying instructions get the latest version. | ||
| sed -i -e "s/cargo install cargo-anneal@[0-9a-zA-Z\.-]*/cargo install cargo-anneal@$VERSION/" anneal/README.md | ||
| # Update Cargo.lock to reflect the version change in Cargo.toml. We must run | ||
| # this in the anneal subdirectory because it is a separate workspace with its | ||
| # own lockfile. | ||
| cd anneal | ||
| cargo generate-lockfile |
| { | ||
| "git": { | ||
| "sha1": "aa7c31671cb5ce509551edafa23c6865df83b180" | ||
| "sha1": "0402dfa593751057a357c89fb8bd140780abd8d5" | ||
| }, | ||
| "path_in_vcs": "" | ||
| } |
+1
-0
@@ -97,2 +97,3 @@ // Copyright 2024 The Fuchsia Authors | ||
| println!("cargo:rustc-check-cfg=cfg(zerocopy_inline_always)"); | ||
| println!("cargo:rustc-check-cfg=cfg(zerocopy_unstable_ptr)"); | ||
| } | ||
@@ -99,0 +100,0 @@ |
+3
-3
@@ -122,3 +122,3 @@ # This file is automatically @generated by Cargo. | ||
| name = "zerocopy" | ||
| version = "0.8.48" | ||
| version = "0.8.49-alpha" | ||
| dependencies = [ | ||
@@ -136,5 +136,5 @@ "elain", | ||
| name = "zerocopy-derive" | ||
| version = "0.8.48" | ||
| version = "0.8.49-alpha" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" | ||
| checksum = "0a7e92e6ea138f1872de93d2eeb552e6b6e64cffc8fc9a6a04db9856f931d3e4" | ||
| dependencies = [ | ||
@@ -141,0 +141,0 @@ "proc-macro2", |
+8
-3
@@ -13,6 +13,11 @@ #!/usr/bin/env bash | ||
| # When running inside the Docker container in CI, we don't copy `tools/.cargo`. | ||
| CONFIG_ARGS=() | ||
| if [[ -f "tools/.cargo/config.toml" ]]; then | ||
| CONFIG_ARGS=("--config" "tools/.cargo/config.toml") | ||
| fi | ||
| # Build `cargo-zerocopy` without any RUSTFLAGS or CARGO_TARGET_DIR set in the | ||
| # environment | ||
| env -u RUSTFLAGS -u CARGO_TARGET_DIR cargo +stable build --config tools/.cargo/config.toml --manifest-path tools/Cargo.toml -p cargo-zerocopy -q | ||
| # Thin wrapper around the `cargo-zerocopy` binary in `tools/cargo-zerocopy` | ||
| ./tools/target/debug/cargo-zerocopy $@ | ||
| env -u RUSTFLAGS -u CARGO_TARGET_DIR cargo +stable build "${CONFIG_ARGS[@]}" --manifest-path tools/cargo-zerocopy/Cargo.toml -p cargo-zerocopy -q | ||
| ./tools/target/debug/cargo-zerocopy "$@" |
+11
-4
@@ -16,3 +16,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| name = "zerocopy" | ||
| version = "0.8.48" | ||
| version = "0.8.49-alpha" | ||
| authors = [ | ||
@@ -71,2 +71,9 @@ "Joshua Liebow-Feeser <joshlf@google.com>", | ||
| ] | ||
| targets = [ | ||
| "x86_64-unknown-linux-gnu", | ||
| "x86_64-apple-darwin", | ||
| "x86_64-pc-windows-msvc", | ||
| "i686-unknown-linux-gnu", | ||
| "i686-pc-windows-msvc", | ||
| ] | ||
@@ -387,3 +394,3 @@ [package.metadata.playground] | ||
| [dependencies.zerocopy-derive] | ||
| version = "=0.8.48" | ||
| version = "=0.8.49-alpha" | ||
| optional = true | ||
@@ -412,5 +419,5 @@ | ||
| [dev-dependencies.zerocopy-derive] | ||
| version = "=0.8.48" | ||
| version = "=0.8.49-alpha" | ||
| [target."cfg(any())".dependencies.zerocopy-derive] | ||
| version = "=0.8.48" | ||
| version = "=0.8.49-alpha" |
+15
-2
@@ -19,3 +19,16 @@ #!/usr/bin/env bash | ||
| find . -iname '*.rs' -type f -not -path './target/*' -not -iname '*.expected.rs' -not -path './vendor/*' -not -path './tools/vendor/*' -not -path './tools/hermes/*' -print0 | xargs -0 --no-run-if-empty ./cargo.sh +nightly fmt $FMT_FLAGS -- >&2 | ||
| find ./tools/hermes -iname '*.rs' -type f -not -path './tools/hermes/target/*' -not -iname '*.expected.rs' -not -path './tools/hermes/tests/fixtures/*' -not -path './tools/hermes/tests/ui/*' -print0 | xargs -0 --no-run-if-empty ./cargo.sh +nightly fmt $FMT_FLAGS --manifest-path tools/hermes/Cargo.toml -- >&2 | ||
| find . -iname '*.rs' -type f \ | ||
| -not -path './anneal/*' \ | ||
| -not -path './target/*' \ | ||
| -not -path './tools/target/*' \ | ||
| -not -iname '*.expected.rs' \ | ||
| -not -path './vendor/*' \ | ||
| -not -path './tools/vendor/*' \ | ||
| -print0 | xargs -0 --no-run-if-empty ./cargo.sh +nightly fmt $FMT_FLAGS -- >&2 | ||
| find ./anneal -iname '*.rs' -type f \ | ||
| -not -path './anneal/target/*' \ | ||
| -not -path './anneal/vendor/*' \ | ||
| -not -path './anneal/tests/fixtures/*' \ | ||
| -not -path './anneal/tests/ui/*' \ | ||
| -print0 | xargs -0 --no-run-if-empty ./cargo.sh +nightly fmt $FMT_FLAGS --manifest-path anneal/Cargo.toml -- >&2 |
@@ -90,6 +90,9 @@ #!/usr/bin/env python3 | ||
| if not file_objects or len(file_objects) != args.expected_count: | ||
| # This can happen when a PR contains a large number of files. It | ||
| # doesn't necessarily represent a bug, so we treat this as | ||
| # `NOT_APPROVED` rather than `TECHNICAL_ERROR`. | ||
| print( | ||
| f"::error::❌ File truncation mismatch or empty PR. Expected {args.expected_count}, got {len(file_objects) if file_objects else 0}." | ||
| ) | ||
| sys.exit(TECHNICAL_ERROR) | ||
| sys.exit(NOT_APPROVED) | ||
@@ -96,0 +99,0 @@ if not all(isinstance(obj, list) for obj in file_objects): |
@@ -368,3 +368,3 @@ // Copyright 2024 The Fuchsia Authors | ||
| let len = kani::any(); | ||
| kani::assume(len <= isize::MAX as usize); | ||
| kani::assume(len <= crate::DstLayout::MAX_SIZE); | ||
| vec![0u8; len] | ||
@@ -371,0 +371,0 @@ } |
+2
-0
@@ -665,2 +665,3 @@ // Copyright 2024 The Fuchsia Authors | ||
| type Mapped = crate::ValidityError<NewSrc, Dst>; | ||
| #[inline] | ||
| fn map<F: FnOnce(Src) -> NewSrc>(self, f: F) -> Self::Mapped { | ||
@@ -804,2 +805,3 @@ self.map_src(f) | ||
| #[inline] | ||
| fn map<F: FnOnce(Src) -> NewSrc>(self, f: F) -> Self::Mapped { | ||
@@ -806,0 +808,0 @@ self.map_src(f) |
+22
-10
@@ -129,3 +129,3 @@ // Copyright 2024 The Fuchsia Authors | ||
| #[inline] | ||
| pub(crate) fn from_ref(ptr: &'a T) -> Self { | ||
| pub fn from_ref(ptr: &'a T) -> Self { | ||
| let ptr = NonNull::from(ptr); | ||
@@ -156,3 +156,3 @@ // SAFETY: | ||
| #[inline] | ||
| pub(crate) fn from_mut(ptr: &'a mut T) -> Self { | ||
| pub fn from_mut(ptr: &'a mut T) -> Self { | ||
| let ptr = NonNull::from(ptr); | ||
@@ -223,3 +223,5 @@ // SAFETY: | ||
| /// Extracts the metadata of this `ptr`. | ||
| pub(crate) fn meta(self) -> MetadataOf<T> { | ||
| #[inline] | ||
| #[must_use] | ||
| pub fn meta(self) -> MetadataOf<T> { | ||
| let meta = T::pointer_to_metadata(self.as_ptr()); | ||
@@ -240,3 +242,4 @@ // SAFETY: By invariant on `PtrInner`, `self.as_non_null()` addresses no | ||
| #[inline] | ||
| pub(crate) unsafe fn with_meta(self, meta: T::PointerMetadata) -> Self | ||
| #[must_use] | ||
| pub unsafe fn with_meta(self, meta: T::PointerMetadata) -> Self | ||
| where | ||
@@ -295,3 +298,5 @@ T: KnownLayout, | ||
| /// the right pointer to satisfy `T`'s padding requirements. | ||
| pub(crate) unsafe fn split_at_unchecked( | ||
| #[inline] | ||
| #[must_use] | ||
| pub unsafe fn split_at_unchecked( | ||
| self, | ||
@@ -331,3 +336,5 @@ l_len: crate::util::MetadataOf<T>, | ||
| /// Produces the trailing slice of `self`. | ||
| pub(crate) fn trailing_slice(self) -> PtrInner<'a, [T::Elem]> | ||
| #[inline] | ||
| #[must_use] | ||
| pub fn trailing_slice(self) -> PtrInner<'a, [T::Elem]> | ||
| where | ||
@@ -388,3 +395,5 @@ T: SplitAt, | ||
| /// `range` is a valid range (`start <= end`) and `end <= self.meta()`. | ||
| pub(crate) unsafe fn slice_unchecked(self, range: Range<usize>) -> Self { | ||
| #[inline] | ||
| #[must_use] | ||
| pub unsafe fn slice_unchecked(self, range: Range<usize>) -> Self { | ||
| let base = self.as_non_null().cast::<T>().as_ptr(); | ||
@@ -434,3 +443,4 @@ | ||
| /// Iteratively projects the elements `PtrInner<T>` from `PtrInner<[T]>`. | ||
| pub(crate) fn iter(&self) -> impl Iterator<Item = PtrInner<'a, T>> { | ||
| #[inline] | ||
| pub fn iter(&self) -> impl Iterator<Item = PtrInner<'a, T>> { | ||
| // FIXME(#429): Once `NonNull::cast` documents that it preserves | ||
@@ -509,3 +519,5 @@ // provenance, cite those docs. | ||
| #[allow(clippy::wrong_self_convention)] | ||
| pub(crate) fn as_slice(self) -> PtrInner<'a, [T]> { | ||
| #[inline] | ||
| #[must_use] | ||
| pub fn as_slice(self) -> PtrInner<'a, [T]> { | ||
| let start = self.as_non_null().cast::<T>().as_ptr(); | ||
@@ -558,3 +570,3 @@ let slice = core::ptr::slice_from_raw_parts_mut(start, N); | ||
| #[inline] | ||
| pub(crate) fn try_cast_into<U>( | ||
| pub fn try_cast_into<U>( | ||
| self, | ||
@@ -561,0 +573,0 @@ cast_type: CastType, |
@@ -9,3 +9,3 @@ // Copyright 2024 The Fuchsia Authors | ||
| #![allow(missing_copy_implementations, missing_debug_implementations)] | ||
| #![allow(missing_copy_implementations, missing_debug_implementations, missing_docs)] | ||
@@ -269,3 +269,2 @@ //! The parameterized invariants of a [`Ptr`][super::Ptr]. | ||
| #[derive(Copy, Clone, Debug)] | ||
| #[doc(hidden)] | ||
| pub enum BecauseExclusive {} | ||
@@ -276,3 +275,2 @@ | ||
| #[derive(Copy, Clone, Debug)] | ||
| #[doc(hidden)] | ||
| pub enum BecauseImmutable {} | ||
@@ -279,0 +277,0 @@ |
+7
-10
@@ -11,15 +11,13 @@ // Copyright 2023 The Fuchsia Authors | ||
| #![allow(missing_docs)] | ||
| mod inner; | ||
| #[doc(hidden)] | ||
| pub mod invariant; | ||
| mod ptr; | ||
| mod transmute; | ||
| pub mod transmute; | ||
| #[doc(hidden)] | ||
| pub use {inner::PtrInner, transmute::*}; | ||
| #[doc(hidden)] | ||
| pub use { | ||
| invariant::{BecauseExclusive, BecauseImmutable, Read}, | ||
| ptr::*, | ||
| }; | ||
| pub use inner::PtrInner; | ||
| pub use invariant::{BecauseExclusive, BecauseImmutable, Read}; | ||
| pub use ptr::{Ptr, TryWithError}; | ||
| pub use transmute::*; | ||
@@ -48,3 +46,2 @@ use crate::wrappers::ReadOnly; | ||
| #[doc(hidden)] | ||
| pub mod cast { | ||
@@ -51,0 +48,0 @@ use core::{marker::PhantomData, mem}; |
@@ -9,2 +9,4 @@ // Copyright 2025 The Fuchsia Authors | ||
| #![allow(missing_docs)] | ||
| use core::{ | ||
@@ -227,3 +229,2 @@ cell::{Cell, UnsafeCell}, | ||
| #[allow(missing_debug_implementations, missing_copy_implementations)] | ||
| #[doc(hidden)] | ||
| pub enum BecauseInvariantsEq {} | ||
@@ -230,0 +231,0 @@ |
+29
-0
@@ -985,4 +985,33 @@ // Copyright 2023 The Fuchsia Authors | ||
| /// Stub for rendering codegen documentation; used to break build dependency | ||
| /// between benches and zerocopy when re-blessing codegen tests. | ||
| #[allow(unused)] | ||
| #[cfg(not(doc))] | ||
| macro_rules! codegen_section { | ||
| ( | ||
| header = $level:expr, | ||
| bench = $bench:expr, | ||
| format = $format:expr, | ||
| arity = $arity:literal, | ||
| $([ | ||
| $($open:ident)? | ||
| @index $index:literal | ||
| @title $title:literal | ||
| @variant $variant:literal | ||
| ]),* | ||
| ) => { | ||
| "" | ||
| }; | ||
| ( | ||
| header = $level:expr, | ||
| bench = $bench:expr, | ||
| format = $format:expr, | ||
| ) => { | ||
| "" | ||
| }; | ||
| } | ||
| /// Generates the HTML for code generation documentation. | ||
| #[allow(unused)] | ||
| #[cfg(doc)] | ||
| macro_rules! codegen_section { | ||
@@ -989,0 +1018,0 @@ ( |
+45
-28
@@ -145,3 +145,3 @@ // Copyright 2023 The Fuchsia Authors | ||
| kani, | ||
| kani::requires(len <= isize::MAX as usize), | ||
| kani::requires(len <= DstLayout::MAX_SIZE), | ||
| kani::requires(align.is_power_of_two()), | ||
@@ -386,25 +386,25 @@ kani::ensures(|&p| (len + p) % align.get() == 0), | ||
| { | ||
| let align = T::LAYOUT.align.get(); | ||
| if !T::is_valid_metadata(meta) { | ||
| return Err(AllocError); | ||
| } | ||
| let size = match T::size_for_metadata(meta) { | ||
| Some(size) => size, | ||
| // Thanks to the `!T::is_valid_metadata(meta)` check | ||
| // above, this branch is unreachable. Fortunately, the | ||
| // optimizer recognizes this, so replacing this branch | ||
| // with `unreachable_unchecked` produces no codegen | ||
| // improvements. | ||
| None => return Err(AllocError), | ||
| }; | ||
| let align = T::LAYOUT.align.get(); | ||
| // On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a bug in | ||
| // which sufficiently-large allocations (those which, when rounded up to the | ||
| // alignment, overflow `isize`) are not rejected, which can cause undefined | ||
| // behavior. See #64 for details. | ||
| // | ||
| // FIXME(#67): Once our MSRV is > 1.64.0, remove this assertion. | ||
| #[allow(clippy::as_conversions)] | ||
| let max_alloc = (isize::MAX as usize).saturating_sub(align); | ||
| if size > max_alloc { | ||
| return Err(AllocError); | ||
| } | ||
| // FIXME(https://github.com/rust-lang/rust/issues/55724): Use | ||
| // `Layout::repeat` once it's stabilized. | ||
| let layout = Layout::from_size_align(size, align).or(Err(AllocError))?; | ||
| let ptr = if layout.size() != 0 { | ||
| let ptr = if size != 0 { | ||
| // SAFETY: | ||
| // - `align` is derived from a `NonZeroUsize` and is thus non-zero. | ||
| // - `align` is a power of two because, by invariant on | ||
| // `KnownLayout::LAYOUT` `<T as KnownLayout>::LAYOUT` accurately | ||
| // reflects the layout of `T`. | ||
| // - `size`, by invariant on `size_for_metadata` is well-aligned for | ||
| // `align` and, by the check on `T::is_valid_metadata(meta)`, is less | ||
| // than `isize::MAX`. | ||
| let layout: Layout = unsafe { Layout::from_size_align_unchecked(size, align) }; | ||
| // SAFETY: By contract on the caller, `allocate` is either | ||
@@ -425,4 +425,2 @@ // `alloc::alloc::alloc` or `alloc::alloc::alloc_zeroed`. The above | ||
| } else { | ||
| let align = T::LAYOUT.align.get(); | ||
| // We use `transmute` instead of an `as` cast since Miri (with strict | ||
@@ -441,4 +439,4 @@ // provenance enabled) notices and complains that an `as` cast creates a | ||
| let dangling = unsafe { mem::transmute::<usize, *mut u8>(align) }; | ||
| // SAFETY: `dangling` is constructed from `T::LAYOUT.align`, which is a | ||
| // `NonZeroUsize`, which is guaranteed to be non-zero. | ||
| // SAFETY: `dangling` is constructed from `align`, which is derived from | ||
| // a `NonZeroUsize`, which is guaranteed to be non-zero. | ||
| // | ||
@@ -472,3 +470,3 @@ // `Box<[T]>` does not allocate when `T` is zero-sized or when `len` is | ||
| /// A witness type for metadata of a valid instance of `&T`. | ||
| pub(crate) struct MetadataOf<T: ?Sized + KnownLayout> { | ||
| pub struct MetadataOf<T: ?Sized + KnownLayout> { | ||
| /// # Safety | ||
@@ -484,2 +482,3 @@ /// | ||
| impl<T: ?Sized + KnownLayout> Clone for MetadataOf<T> { | ||
| #[inline] | ||
| fn clone(&self) -> Self { | ||
@@ -490,2 +489,12 @@ *self | ||
| impl<T: ?Sized + KnownLayout> core::fmt::Debug for MetadataOf<T> | ||
| where | ||
| T::PointerMetadata: core::fmt::Debug, | ||
| { | ||
| #[inline] | ||
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
| f.debug_struct("MetadataOf").field("meta", &self.meta).finish() | ||
| } | ||
| } | ||
| impl<T: ?Sized> MetadataOf<T> | ||
@@ -589,7 +598,15 @@ where | ||
| None => T::LAYOUT, | ||
| // This can return `None` if the metadata describes an object | ||
| // which can't fit in an `isize`. | ||
| // This can return `Err(MetadataCastError::Size)` if the | ||
| // metadata describes an object which can't fit in an `isize`. | ||
| Some(meta) => { | ||
| if !T::is_valid_metadata(meta) { | ||
| return Err(MetadataCastError::Size); | ||
| } | ||
| let size = match T::size_for_metadata(meta) { | ||
| Some(size) => size, | ||
| // Thanks to the `!T::is_valid_metadata(meta)` check | ||
| // above, this branch is unreachable. Fortunately, the | ||
| // optimizer recognizes this, so replacing this branch | ||
| // with `unreachable_unchecked` produces no codegen | ||
| // improvements. | ||
| None => return Err(MetadataCastError::Size), | ||
@@ -659,3 +676,3 @@ }; | ||
| pub(crate) use len_of::MetadataOf; | ||
| pub use len_of::MetadataOf; | ||
@@ -662,0 +679,0 @@ /// Since we support multiple versions of Rust, there are often features which |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet