rust/zerocopy-derive/derive/known_layout.rs

Source file repositories/reference/linux-study-clean/rust/zerocopy-derive/derive/known_layout.rs

File Facts

System
Linux kernel
Corpus path
rust/zerocopy-derive/derive/known_layout.rs
Extension
.rs
Size
14807 bytes
Lines
351
Domain
Rust Kernel Layer
Bucket
Rust API Membrane
Inferred role
Rust Kernel Layer: implementation source
Status
source implementation candidate

Why This File Exists

Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.

Dependency Surface

Detected Declarations

Annotated Snippet

fn only_derive_is_allowed_to_implement_this_trait() {}

                type PointerMetadata = <#ident #ty_generics as #zerocopy_crate::KnownLayout>::PointerMetadata;

                type MaybeUninit = Self;

                const LAYOUT: #zerocopy_crate::DstLayout = <#ident #ty_generics as #zerocopy_crate::KnownLayout>::LAYOUT;

                #methods
            }
        }
    };

    Some((SelfBounds::None, inner_extras, Some(outer_extras)))
}

pub(crate) fn derive(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> {
    // If this is a `repr(C)` struct, then `c_struct_repr` contains the entire
    // `repr` attribute.
    let c_struct_repr = match &ctx.ast.data {
        Data::Struct(..) => {
            let repr = StructUnionRepr::from_attrs(&ctx.ast.attrs)?;
            if repr.is_c() {
                Some(repr)
            } else {
                None
            }
        }
        Data::Enum(..) | Data::Union(..) => None,
    };

    let fields = ctx.ast.data.fields();

    let (self_bounds, inner_extras, outer_extras) = c_struct_repr
        .as_ref()
        .and_then(|repr| {
            derive_known_layout_for_repr_c_struct(ctx, repr, &fields)
        })
        .unwrap_or_else(|| {
            let zerocopy_crate = &ctx.zerocopy_crate;
            let core = ctx.core_path();

            // For enums, unions, and non-`repr(C)` structs, we require that
            // `Self` is sized, and as a result don't need to reason about the
            // internals of the type.
            (
                SelfBounds::SIZED,
                quote!(
                    type PointerMetadata = ();
                    type MaybeUninit =
                        #core::mem::MaybeUninit<Self>;

                    // SAFETY: `LAYOUT` is guaranteed to accurately describe the
                    // layout of `Self`, because that is the documented safety
                    // contract of `DstLayout::for_type`.
                    const LAYOUT: #zerocopy_crate::DstLayout = #zerocopy_crate::DstLayout::for_type::<Self>();

                    // SAFETY: `.cast` preserves address and provenance.
                    //
                    // FIXME(#429): Add documentation to `.cast` that promises that
                    // it preserves provenance.
                    #[inline(always)]
                    fn raw_from_ptr_len(bytes: #core::ptr::NonNull<u8>, _meta: ()) -> #core::ptr::NonNull<Self> {
                        bytes.cast::<Self>()
                    }

                    #[inline(always)]
                    fn pointer_to_metadata(_ptr: *mut Self) -> () {}
                ),
                None,
            )
        });
    Ok(match &ctx.ast.data {
        Data::Struct(strct) => {
            let require_trait_bound_on_field_types =
                if matches!(self_bounds, SelfBounds::All(&[Trait::Sized])) {
                    FieldBounds::None
                } else {
                    FieldBounds::TRAILING_SELF
                };

            // A bound on the trailing field is required, since structs are
            // unsized if their trailing field is unsized. Reflecting the layout
            // of an usized trailing field requires that the field is
            // `KnownLayout`.
            ImplBlockBuilder::new(
                ctx,
                strct,
                Trait::KnownLayout,
                require_trait_bound_on_field_types,

Annotation

Implementation Notes