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.
This commit is contained in:
zachs18 2023-09-05 14:36:10 -05:00 committed by GitHub
parent db69feee1e
commit 58445b1250
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 88 additions and 38 deletions

View File

@ -23,19 +23,69 @@ use crate::traits::{
/// - All fields in the struct must implement `Pod` /// - All fields in the struct must implement `Pod`
/// - The struct must be `#[repr(C)]` or `#[repr(transparent)]` /// - The struct must be `#[repr(C)]` or `#[repr(transparent)]`
/// - The struct must not contain any padding bytes /// - 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 /// ```rust
/// # use std::marker::PhantomData;
/// # use bytemuck_derive::{Pod, Zeroable}; /// # use bytemuck_derive::{Pod, Zeroable};
///
/// #[derive(Copy, Clone, Pod, Zeroable)] /// #[derive(Copy, Clone, Pod, Zeroable)]
/// #[repr(C)] /// #[repr(C)]
/// struct Test { /// struct Test {
/// a: u16, /// a: u16,
/// b: u16, /// b: u16,
/// } /// }
///
/// #[derive(Copy, Clone, Pod, Zeroable)]
/// #[repr(transparent)]
/// struct Generic<A, B> {
/// a: A,
/// b: PhantomData<B>,
/// }
/// ```
///
/// 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: 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, B> {
/// a: A,
/// b: PhantomData<B>,
/// }
///
/// let _: u32 = bytemuck::cast(Generic { a: 4u32, b: PhantomData::<u32> });
/// ```
///
/// ```compile_fail
/// # use bytemuck::{Pod, Zeroable};
/// # use std::marker::PhantomData;
/// # #[derive(Copy, Clone, Pod, Zeroable)]
/// # #[repr(transparent)]
/// # struct Generic<A, B> {
/// # a: A,
/// # b: PhantomData<B>,
/// # }
/// struct NotPod;
///
/// let _: u32 = bytemuck::cast(Generic { a: 4u32, b: PhantomData::<NotPod> });
/// ``` /// ```
#[proc_macro_derive(Pod)] #[proc_macro_derive(Pod)]
pub fn derive_pod(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 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 be `#[repr(transparent)]`
/// - The struct must contain the `Wrapped` type /// - 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 /// 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)]` /// you need to specify the `Wrapped` type using `#[transparent(T)]`
/// ///
/// ## Example /// ## Examples
/// ///
/// ```rust /// ```rust
/// # use bytemuck_derive::TransparentWrapper; /// # use bytemuck_derive::TransparentWrapper;
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
///
/// #[derive(Copy, Clone, TransparentWrapper)] /// #[derive(Copy, Clone, TransparentWrapper)]
/// #[repr(transparent)] /// #[repr(transparent)]
/// #[transparent(u16)] /// #[transparent(u16)]
@ -236,6 +286,38 @@ pub fn derive_maybe_pod(
/// extra: PhantomData<T>, /// extra: PhantomData<T>,
/// } /// }
/// ``` /// ```
///
/// 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<T> {
/// inner: u16,
/// extra: PhantomData<T>,
/// }
/// ```
///
/// 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<T> {
/// inner: u16,
/// extra: PhantomData<T>,
/// another_extra: NonTransparentSafeZST, // not `Zeroable`
/// }
/// ```
#[proc_macro_derive(TransparentWrapper, attributes(transparent))] #[proc_macro_derive(TransparentWrapper, attributes(transparent))]
pub fn derive_transparent( pub fn derive_transparent(
input: proc_macro::TokenStream, input: proc_macro::TokenStream,

View File

@ -160,38 +160,6 @@ struct AnyBitPatternTest<A: AnyBitPattern, B: AnyBitPattern> {
b: B, b: B,
} }
/// ```compile_fail
/// use bytemuck::{Pod, Zeroable};
///
/// #[derive(Pod, Zeroable)]
/// #[repr(transparent)]
/// struct TransparentSingle<T>(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>(T);
/// ```compile_fail
/// use bytemuck::TransparentWrapper;
///
/// struct NonTransparentSafeZST;
///
/// #[derive(TransparentWrapper)]
/// #[repr(transparent)]
/// struct Wrapper<T>(T, NonTransparentSafeZST);
/// ```
#[derive(
Debug, Copy, Clone, PartialEq, Eq, Pod, Zeroable, TransparentWrapper,
)]
#[repr(transparent)]
struct TransarentWrapperZstTest<T>(T);
#[test] #[test]
fn fails_cast_contiguous() { fn fails_cast_contiguous() {
let can_cast = CheckedBitPatternEnumWithValues::is_valid_bit_pattern(&5); let can_cast = CheckedBitPatternEnumWithValues::is_valid_bit_pattern(&5);