diff options
author | Benno Lossin <benno.lossin@proton.me> | 2023-08-14 08:47:54 +0000 |
---|---|---|
committer | Miguel Ojeda <ojeda@kernel.org> | 2023-08-21 14:31:49 +0200 |
commit | 4af84c6a85c63bec24611e46bb3de2c0a6602a51 (patch) | |
tree | c6633630be251aebd54733eab8d9cc6c1f8b1655 /rust | |
parent | 7f8977a7fe6df9cdfe489c641058ca5534ec73eb (diff) |
rust: init: update expanded macro explanationrust-6.6
The previous patches changed the internals of the macros resulting in
the example expanded code being outdated. This patch updates the example
and only changes documentation.
Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Link: https://lore.kernel.org/r/20230814084602.25699-14-benno.lossin@proton.me
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Diffstat (limited to 'rust')
-rw-r--r-- | rust/kernel/init/macros.rs | 126 |
1 files changed, 69 insertions, 57 deletions
diff --git a/rust/kernel/init/macros.rs b/rust/kernel/init/macros.rs index 5f0a0bdb9896..cb6e61b6c50b 100644 --- a/rust/kernel/init/macros.rs +++ b/rust/kernel/init/macros.rs @@ -45,7 +45,7 @@ //! #[pinned_drop] //! impl PinnedDrop for Foo { //! fn drop(self: Pin<&mut Self>) { -//! println!("{self:p} is getting dropped."); +//! pr_info!("{self:p} is getting dropped."); //! } //! } //! @@ -170,8 +170,10 @@ //! t: T, //! } //! #[doc(hidden)] -//! impl<'__pin, T> -//! ::core::marker::Unpin for Bar<T> where __Unpin<'__pin, T>: ::core::marker::Unpin {} +//! impl<'__pin, T> ::core::marker::Unpin for Bar<T> +//! where +//! __Unpin<'__pin, T>: ::core::marker::Unpin, +//! {} //! // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users //! // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to //! // UB with only safe code, so we disallow this by giving a trait implementation error using @@ -188,8 +190,9 @@ //! // for safety, but a good sanity check, since no normal code calls `PinnedDrop::drop`. //! #[allow(non_camel_case_types)] //! trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {} -//! impl<T: ::kernel::init::PinnedDrop> -//! UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {} +//! impl< +//! T: ::kernel::init::PinnedDrop, +//! > UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {} //! impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {} //! }; //! ``` @@ -219,7 +222,7 @@ //! // return type and shadow it later when we insert the arbitrary user code. That way //! // there will be no possibility of returning without `unsafe`. //! struct __InitOk; -//! // Get the pin-data type from the initialized type. +//! // Get the data about fields from the supplied type. //! // - the function is unsafe, hence the unsafe block //! // - we `use` the `HasPinData` trait in the block, it is only available in that //! // scope. @@ -227,8 +230,7 @@ //! use ::kernel::init::__internal::HasPinData; //! Self::__pin_data() //! }; -//! // Use `data` to help with type inference, the closure supplied will have the type -//! // `FnOnce(*mut Self) -> Result<__InitOk, Infallible>`. +//! // Ensure that `data` really is of type `PinData` and help with type inference: //! let init = ::kernel::init::__internal::PinData::make_closure::< //! _, //! __InitOk, @@ -236,71 +238,75 @@ //! >(data, move |slot| { //! { //! // Shadow the structure so it cannot be used to return early. If a user -//! // tries to write `return Ok(__InitOk)`, then they get a type error, since -//! // that will refer to this struct instead of the one defined above. +//! // tries to write `return Ok(__InitOk)`, then they get a type error, +//! // since that will refer to this struct instead of the one defined +//! // above. //! struct __InitOk; //! // This is the expansion of `t,`, which is syntactic sugar for `t: t,`. -//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) }; -//! // Since initialization could fail later (not in this case, since the error -//! // type is `Infallible`) we will need to drop this field if there is an -//! // error later. This `DropGuard` will drop the field when it gets dropped -//! // and has not yet been forgotten. We make a reference to it, so users -//! // cannot `mem::forget` it from the initializer, since the name is the same -//! // as the field (including hygiene). -//! let t = &unsafe { -//! ::kernel::init::__internal::DropGuard::new( -//! ::core::addr_of_mut!((*slot).t), -//! ) +//! { +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) }; +//! } +//! // Since initialization could fail later (not in this case, since the +//! // error type is `Infallible`) we will need to drop this field if there +//! // is an error later. This `DropGuard` will drop the field when it gets +//! // dropped and has not yet been forgotten. +//! let t = unsafe { +//! ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t)) //! }; //! // Expansion of `x: 0,`: -//! // Since this can be an arbitrary expression we cannot place it inside of -//! // the `unsafe` block, so we bind it here. -//! let x = 0; -//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) }; +//! // Since this can be an arbitrary expression we cannot place it inside +//! // of the `unsafe` block, so we bind it here. +//! { +//! let x = 0; +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) }; +//! } //! // We again create a `DropGuard`. -//! let x = &unsafe { -//! ::kernel::init::__internal::DropGuard::new( -//! ::core::addr_of_mut!((*slot).x), -//! ) +//! let x = unsafe { +//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x)) //! }; -//! +//! // Since initialization has successfully completed, we can now forget +//! // the guards. This is not `mem::forget`, since we only have +//! // `&DropGuard`. +//! ::core::mem::forget(x); +//! ::core::mem::forget(t); //! // Here we use the type checker to ensure that every field has been //! // initialized exactly once, since this is `if false` it will never get //! // executed, but still type-checked. -//! // Additionally we abuse `slot` to automatically infer the correct type for -//! // the struct. This is also another check that every field is accessible -//! // from this scope. +//! // Additionally we abuse `slot` to automatically infer the correct type +//! // for the struct. This is also another check that every field is +//! // accessible from this scope. //! #[allow(unreachable_code, clippy::diverging_sub_expression)] -//! if false { +//! let _ = || { //! unsafe { //! ::core::ptr::write( //! slot, //! Self { -//! // We only care about typecheck finding every field here, -//! // the expression does not matter, just conjure one using -//! // `panic!()`: +//! // We only care about typecheck finding every field +//! // here, the expression does not matter, just conjure +//! // one using `panic!()`: //! t: ::core::panic!(), //! x: ::core::panic!(), //! }, //! ); //! }; -//! } -//! // Since initialization has successfully completed, we can now forget the -//! // guards. This is not `mem::forget`, since we only have `&DropGuard`. -//! unsafe { ::kernel::init::__internal::DropGuard::forget(t) }; -//! unsafe { ::kernel::init::__internal::DropGuard::forget(x) }; +//! }; //! } //! // We leave the scope above and gain access to the previously shadowed //! // `__InitOk` that we need to return. //! Ok(__InitOk) //! }); //! // Change the return type from `__InitOk` to `()`. -//! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> { +//! let init = move | +//! slot, +//! | -> ::core::result::Result<(), ::core::convert::Infallible> { //! init(slot).map(|__InitOk| ()) //! }; //! // Construct the initializer. //! let init = unsafe { -//! ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init) +//! ::kernel::init::pin_init_from_closure::< +//! _, +//! ::core::convert::Infallible, +//! >(init) //! }; //! init //! } @@ -374,7 +380,10 @@ //! b: Bar<u32>, //! } //! #[doc(hidden)] -//! impl<'__pin> ::core::marker::Unpin for Foo where __Unpin<'__pin>: ::core::marker::Unpin {} +//! impl<'__pin> ::core::marker::Unpin for Foo +//! where +//! __Unpin<'__pin>: ::core::marker::Unpin, +//! {} //! // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to //! // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like //! // before, instead we implement `Drop` here and delegate to `PinnedDrop`. @@ -403,7 +412,7 @@ //! #[pinned_drop] //! impl PinnedDrop for Foo { //! fn drop(self: Pin<&mut Self>) { -//! println!("{self:p} is getting dropped."); +//! pr_info!("{self:p} is getting dropped."); //! } //! } //! ``` @@ -414,7 +423,7 @@ //! // `unsafe`, full path and the token parameter are added, everything else stays the same. //! unsafe impl ::kernel::init::PinnedDrop for Foo { //! fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) { -//! println!("{self:p} is getting dropped."); +//! pr_info!("{self:p} is getting dropped."); //! } //! } //! ``` @@ -449,18 +458,21 @@ //! >(data, move |slot| { //! { //! struct __InitOk; -//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) }; -//! let a = &unsafe { +//! { +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) }; +//! } +//! let a = unsafe { //! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a)) //! }; -//! let b = Bar::new(36); +//! let init = Bar::new(36); //! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? }; -//! let b = &unsafe { +//! let b = unsafe { //! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b)) //! }; -//! +//! ::core::mem::forget(b); +//! ::core::mem::forget(a); //! #[allow(unreachable_code, clippy::diverging_sub_expression)] -//! if false { +//! let _ = || { //! unsafe { //! ::core::ptr::write( //! slot, @@ -470,13 +482,13 @@ //! }, //! ); //! }; -//! } -//! unsafe { ::kernel::init::__internal::DropGuard::forget(a) }; -//! unsafe { ::kernel::init::__internal::DropGuard::forget(b) }; +//! }; //! } //! Ok(__InitOk) //! }); -//! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> { +//! let init = move | +//! slot, +//! | -> ::core::result::Result<(), ::core::convert::Infallible> { //! init(slot).map(|__InitOk| ()) //! }; //! let init = unsafe { |