From 58445b125091ea65a80bf7b490adbaa90bfc650d Mon Sep 17 00:00:00 2001 From: zachs18 <8355914+zachs18@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:36:10 -0500 Subject: [PATCH] Fix derive non-run doctests. (#204) Doctests only run in the crate proper; doctests inside of integration tests are not run. Move the existing doctests from derive/tests/basic.rs to derive/lib.rs, expanding them to make them better for documentation as well. --- derive/src/lib.rs | 94 ++++++++++++++++++++++++++++++++++++++++--- derive/tests/basic.rs | 32 --------------- 2 files changed, 88 insertions(+), 38 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 23ddf5e..7ca9527 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -23,19 +23,69 @@ use crate::traits::{ /// - All fields in the struct must implement `Pod` /// - The struct must be `#[repr(C)]` or `#[repr(transparent)]` /// - The struct must not contain any padding bytes -/// - The struct contains no generic parameters +/// - The struct contains no generic parameters, if it is not +/// `#[repr(transparent)]` /// -/// ## Example +/// ## Examples /// /// ```rust +/// # use std::marker::PhantomData; /// # use bytemuck_derive::{Pod, Zeroable}; -/// /// #[derive(Copy, Clone, Pod, Zeroable)] /// #[repr(C)] /// struct Test { /// a: u16, /// b: u16, /// } +/// +/// #[derive(Copy, Clone, Pod, Zeroable)] +/// #[repr(transparent)] +/// struct Generic { +/// a: A, +/// b: PhantomData, +/// } +/// ``` +/// +/// If the struct is generic, it must be `#[repr(transparent)]` also. +/// +/// ```compile_fail +/// # use bytemuck::{Pod, Zeroable}; +/// # use std::marker::PhantomData; +/// #[derive(Copy, Clone, Pod, Zeroable)] +/// #[repr(C)] // must be `#[repr(transparent)]` +/// struct Generic { +/// a: A, +/// } +/// ``` +/// +/// If the struct is generic and `#[repr(transparent)]`, then it is only `Pod` +/// when all of its generics are `Pod`, not just its fields. +/// +/// ``` +/// # use bytemuck::{Pod, Zeroable}; +/// # use std::marker::PhantomData; +/// #[derive(Copy, Clone, Pod, Zeroable)] +/// #[repr(transparent)] +/// struct Generic { +/// a: A, +/// b: PhantomData, +/// } +/// +/// let _: u32 = bytemuck::cast(Generic { a: 4u32, b: PhantomData:: }); +/// ``` +/// +/// ```compile_fail +/// # use bytemuck::{Pod, Zeroable}; +/// # use std::marker::PhantomData; +/// # #[derive(Copy, Clone, Pod, Zeroable)] +/// # #[repr(transparent)] +/// # struct Generic { +/// # a: A, +/// # b: PhantomData, +/// # } +/// struct NotPod; +/// +/// let _: u32 = bytemuck::cast(Generic { a: 4u32, b: PhantomData:: }); /// ``` #[proc_macro_derive(Pod)] pub fn derive_pod(input: proc_macro::TokenStream) -> proc_macro::TokenStream { @@ -217,17 +267,17 @@ pub fn derive_maybe_pod( /// /// - The struct must be `#[repr(transparent)]` /// - The struct must contain the `Wrapped` type +/// - Any ZST fields must be [`Zeroable`][derive@Zeroable]. /// /// If the struct only contains a single field, the `Wrapped` type will -/// automatically be determined if there is more then one field in the struct, +/// automatically be determined. If there is more then one field in the struct, /// you need to specify the `Wrapped` type using `#[transparent(T)]` /// -/// ## Example +/// ## Examples /// /// ```rust /// # use bytemuck_derive::TransparentWrapper; /// # use std::marker::PhantomData; -/// /// #[derive(Copy, Clone, TransparentWrapper)] /// #[repr(transparent)] /// #[transparent(u16)] @@ -236,6 +286,38 @@ pub fn derive_maybe_pod( /// extra: PhantomData, /// } /// ``` +/// +/// If the struct contains more than one field, the `Wrapped` type must be +/// explicitly specified. +/// +/// ```rust,compile_fail +/// # use bytemuck_derive::TransparentWrapper; +/// # use std::marker::PhantomData; +/// #[derive(Copy, Clone, TransparentWrapper)] +/// #[repr(transparent)] +/// // missing `#[transparent(u16)]` +/// struct Test { +/// inner: u16, +/// extra: PhantomData, +/// } +/// ``` +/// +/// Any ZST fields must be `Zeroable`. +/// +/// ```rust,compile_fail +/// # use bytemuck_derive::TransparentWrapper; +/// # use std::marker::PhantomData; +/// struct NonTransparentSafeZST; +/// +/// #[derive(TransparentWrapper)] +/// #[repr(transparent)] +/// #[transparent(u16)] +/// struct Test { +/// inner: u16, +/// extra: PhantomData, +/// another_extra: NonTransparentSafeZST, // not `Zeroable` +/// } +/// ``` #[proc_macro_derive(TransparentWrapper, attributes(transparent))] pub fn derive_transparent( input: proc_macro::TokenStream, diff --git a/derive/tests/basic.rs b/derive/tests/basic.rs index 1be54c4..b719c23 100644 --- a/derive/tests/basic.rs +++ b/derive/tests/basic.rs @@ -160,38 +160,6 @@ struct AnyBitPatternTest { b: B, } -/// ```compile_fail -/// use bytemuck::{Pod, Zeroable}; -/// -/// #[derive(Pod, Zeroable)] -/// #[repr(transparent)] -/// struct TransparentSingle(T); -/// -/// struct NotPod(u32); -/// -/// let _: u32 = bytemuck::cast(TransparentSingle(NotPod(0u32))); -/// ``` -#[derive( - Debug, Copy, Clone, PartialEq, Eq, Pod, Zeroable, TransparentWrapper, -)] -#[repr(transparent)] -struct NewtypeWrapperTest(T); - -/// ```compile_fail -/// use bytemuck::TransparentWrapper; -/// -/// struct NonTransparentSafeZST; -/// -/// #[derive(TransparentWrapper)] -/// #[repr(transparent)] -/// struct Wrapper(T, NonTransparentSafeZST); -/// ``` -#[derive( - Debug, Copy, Clone, PartialEq, Eq, Pod, Zeroable, TransparentWrapper, -)] -#[repr(transparent)] -struct TransarentWrapperZstTest(T); - #[test] fn fails_cast_contiguous() { let can_cast = CheckedBitPatternEnumWithValues::is_valid_bit_pattern(&5);