Skip to content

Commit 8e3fa16

Browse files
committed
Improve docs
1 parent 43f296c commit 8e3fa16

File tree

2 files changed

+81
-35
lines changed

2 files changed

+81
-35
lines changed

rust/kernel/init.rs

+80-35
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,21 @@
2222
//!
2323
//! ## Directly creating an in-place constructor
2424
//!
25+
//! If you want to use [`PinInit`], then you will have to annotate your struct with [`#[pin_project]`].
26+
//! It is a macro that uses `#[pin]` as a marker for [structurally pinned fields].
27+
//!
2528
//! ```rust
26-
//! # use kernel::prelude::*;
29+
//! use kernel::{prelude::*, sync::Mutex, new_mutex};
2730
//! # use core::pin::Pin;
2831
//! #[pin_project]
2932
//! struct Foo {
30-
//! a: usize,
33+
//! #[pin]
34+
//! a: Mutex<usize>,
3135
//! b: u32,
3236
//! }
3337
//!
3438
//! let foo = pin_init!(Foo {
35-
//! a: 42,
39+
//! a: new_mutex!(42, "Foo::a"),
3640
//! b: 24,
3741
//! });
3842
//! # let foo: Result<Pin<Box<Foo>>> = Box::pin_init::<core::convert::Infallible>(foo);
@@ -42,15 +46,16 @@
4246
//! (or just the stack) to actually initialize a `Foo`:
4347
//!
4448
//! ```rust
45-
//! # use kernel::prelude::*;
49+
//! # use kernel::{prelude::*, sync::Mutex, new_mutex};
4650
//! # use core::pin::Pin;
4751
//! # #[pin_project]
4852
//! # struct Foo {
49-
//! # a: usize,
53+
//! # #[pin]
54+
//! # a: Mutex<usize>,
5055
//! # b: u32,
5156
//! # }
5257
//! # let foo = pin_init!(Foo {
53-
//! # a: 42,
58+
//! # a: new_mutex!(42, "Foo::a"),
5459
//! # b: 24,
5560
//! # });
5661
//! let foo: Result<Pin<Box<Foo>>> = Box::pin_init::<core::convert::Infallible>(foo);
@@ -91,6 +96,7 @@
9196
//!
9297
//! [sync]: ../sync/index.html
9398
//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
99+
//! [structurally pinned fields]: https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
94100
//! [stack]: crate::stack_init
95101
//! [`Arc<T>`]: crate::sync::Arc
96102
@@ -111,17 +117,18 @@ use core::{
111117
pub mod __private;
112118
mod pin_project;
113119

114-
/// Initialize a type on the stack.
120+
/// Initialize a type directly on the stack.
115121
///
116122
/// # Examples
117123
///
118124
/// ```rust
119125
/// # #![allow(clippy::blacklisted_name, clippy::new_ret_no_self)]
120-
/// # use kernel::{init, pin_init, stack_init, init::*, macros::pin_project};
126+
/// # use kernel::{init, pin_init, stack_init, init::*, macros::pin_project, sync::Mutex, new_mutex};
121127
/// # use core::pin::Pin;
122128
/// #[pin_project]
123129
/// struct Foo {
124-
/// a: usize,
130+
/// #[pin]
131+
/// a: Mutex<usize>,
125132
/// b: Bar,
126133
/// }
127134
///
@@ -130,7 +137,7 @@ mod pin_project;
130137
/// x: u32,
131138
/// }
132139
///
133-
/// let a = 42;
140+
/// let a = new_mutex!(42, "Foo::a");
134141
///
135142
/// stack_init!(let foo = pin_init!(Foo {
136143
/// a,
@@ -514,18 +521,29 @@ macro_rules! init {
514521
}}
515522
}
516523

517-
//include!("init/pin_project.rs");
518-
519-
/// An initializer for `T`.
524+
/// A pinned initializer for `T`.
525+
///
526+
/// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
527+
/// be [`Box<T>`], [`Arc<T>`], [`UniqueArc<T>`], or even the stack (see [`stack_init!`]). Use the
528+
/// `pin_init` function of a smart pointer like [`Arc::pin_init`] on this.
529+
///
530+
/// Also see the [module description](self).
520531
///
521532
/// # Safety
522533
///
534+
/// When implementing this type you will need to take great care. Also there are probably very few
535+
/// cases where a manual implementation is necessary. Use [`from_value`] and
536+
/// [`pin_init_from_closure`] where possible.
537+
///
523538
/// The [`PinInit::__pinned_init`] function
524539
/// - returns `Ok(())` iff it initialized every field of slot,
525540
/// - returns `Err(err)` iff it encountered an error and then cleaned slot, this means:
526541
/// - slot can be deallocated without UB ocurring,
527542
/// - slot does not need to be dropped,
528543
/// - slot is not partially initialized.
544+
///
545+
/// [`Arc<T>`]: crate::sync::Arc
546+
/// [`Arc::pin_init`]: crate::sync::Arc::pin_init
529547
#[must_use = "An initializer must be used in order to create its value."]
530548
pub unsafe trait PinInit<T, E = Infallible>: Sized {
531549
/// Initializes `slot`.
@@ -541,8 +559,19 @@ pub unsafe trait PinInit<T, E = Infallible>: Sized {
541559

542560
/// An initializer for `T`.
543561
///
562+
/// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
563+
/// be [`Box<T>`], [`Arc<T>`], [`UniqueArc<T>`], or even the stack (see [`stack_init!`]). Use the
564+
/// `init` function of a smart pointer like [`Box::init`] on this. Because [`PinInit<T, E>`] is a
565+
/// super trait, you can use every function that takes it as well.
566+
///
567+
/// Also see the [module description](self).
568+
///
544569
/// # Safety
545570
///
571+
/// When implementing this type you will need to take great care. Also there are probably very few
572+
/// cases where a manual implementation is necessary. Use [`from_value`] and
573+
/// [`init_from_closure`] where possible.
574+
///
546575
/// The [`Init::__init`] function
547576
/// - returns `Ok(())` iff it initialized every field of slot,
548577
/// - returns `Err(err)` iff it encountered an error and then cleaned slot, this means:
@@ -555,6 +584,8 @@ pub unsafe trait PinInit<T, E = Infallible>: Sized {
555584
///
556585
/// Contrary to its supertype [`PinInit<T, E>`] the caller is allowed to
557586
/// move the pointee after initialization.
587+
///
588+
/// [`Arc<T>`]: crate::sync::Arc
558589
#[must_use = "An initializer must be used in order to create its value."]
559590
pub unsafe trait Init<T, E = Infallible>: PinInit<T, E> {
560591
/// Initializes `slot`.
@@ -571,7 +602,25 @@ type Invariant<T> = PhantomData<fn(T) -> T>;
571602

572603
struct InitClosure<F, T, E>(F, Invariant<(T, E)>);
573604

574-
/// Creates a new Init from the given closure
605+
unsafe impl<T, F, E> PinInit<T, E> for InitClosure<F, T, E>
606+
where
607+
F: FnOnce(*mut T) -> Result<(), E>,
608+
{
609+
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
610+
(self.0)(slot)
611+
}
612+
}
613+
614+
unsafe impl<T, F, E> Init<T, E> for InitClosure<F, T, E>
615+
where
616+
F: FnOnce(*mut T) -> Result<(), E>,
617+
{
618+
unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
619+
(self.0)(slot)
620+
}
621+
}
622+
623+
/// Creates a new [`Init<T, E>`] from the given closure.
575624
///
576625
/// # Safety
577626
///
@@ -587,7 +636,7 @@ pub const unsafe fn init_from_closure<T, E>(
587636
) -> impl Init<T, E> {
588637
InitClosure(f, PhantomData)
589638
}
590-
/// Creates a new PinInit from the given closure
639+
/// Creates a new [`PinInit<T, E>`] from the given closure.
591640
///
592641
/// # Safety
593642
///
@@ -604,24 +653,6 @@ pub const unsafe fn pin_init_from_closure<T, E>(
604653
InitClosure(f, PhantomData)
605654
}
606655

607-
unsafe impl<T, F, E> PinInit<T, E> for InitClosure<F, T, E>
608-
where
609-
F: FnOnce(*mut T) -> Result<(), E>,
610-
{
611-
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
612-
(self.0)(slot)
613-
}
614-
}
615-
616-
unsafe impl<T, F, E> Init<T, E> for InitClosure<F, T, E>
617-
where
618-
F: FnOnce(*mut T) -> Result<(), E>,
619-
{
620-
unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
621-
(self.0)(slot)
622-
}
623-
}
624-
625656
/// Trait facilitating pinned destruction.
626657
///
627658
/// Use [`pinned_drop`] to implement this trait safely:
@@ -648,10 +679,14 @@ where
648679
///
649680
/// [`pinned_drop`]: kernel::macros::pinned_drop
650681
pub unsafe trait PinnedDrop {
682+
/// Executes the pinned destructor of this type.
683+
///
651684
/// # Safety
652685
///
653686
/// Only call this from `<Self as Drop>::drop`.
654687
unsafe fn drop(self: Pin<&mut Self>);
688+
689+
// used by `pinned_drop` to ensure that only safe operations are used in `drop`.
655690
#[doc(hidden)]
656691
fn __ensure_no_unsafe_op_in_drop(self: Pin<&mut Self>);
657692
}
@@ -734,8 +769,12 @@ impl<T> InPlaceInit<T> for UniqueArc<T> {
734769
/// The bit pattern consisting of only zeroes must be a valid bit pattern for the type.
735770
pub unsafe trait Zeroable {}
736771

737-
/// Create a new zeroed T
772+
/// Create a new zeroed T.
773+
///
774+
/// The returned initializer will write `0x00` to every byte of the given slot.
738775
pub fn zeroed<T: Zeroable + Unpin>() -> impl Init<T> {
776+
// SAFETY: because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`
777+
// and because we write all zeroes, the memory is initialized.
739778
unsafe {
740779
init_from_closure(|slot: *mut T| {
741780
slot.write_bytes(0, 1);
@@ -745,12 +784,18 @@ pub fn zeroed<T: Zeroable + Unpin>() -> impl Init<T> {
745784
}
746785

747786
/// An initializer that leaves the memory uninitialized.
787+
///
788+
/// The initializer is a no-op. The slot memory is not changed.
748789
pub fn uninit<T>() -> impl Init<MaybeUninit<T>> {
790+
// SAFETY: The memory is allowed to be uninitialized.
749791
unsafe { init_from_closure(|_| Ok(())) }
750792
}
751793

752-
/// Convert a value into an initializer
794+
/// Convert a value into an initializer.
795+
///
796+
/// Directly moves the value into the given slot.
753797
pub fn from_value<T>(value: T) -> impl Init<T> {
798+
// SAFETY: we use the value to initialize the slot.
754799
unsafe {
755800
init_from_closure(move |slot: *mut T| {
756801
slot.write(value);

rust/kernel/init/pin_project.rs

+1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ macro_rules! pin_project {
239239
$($pinned)*
240240
}
241241

242+
#[doc(hidden)]
242243
impl<'__pin, $($impl_generics)*> ::core::marker::Unpin for $name<$($ty_generics)*>
243244
where
244245
__Unpin<'__pin, $($ty_generics)*>: ::core::marker::Unpin,

0 commit comments

Comments
 (0)