1

rust: init: change the generated name of guard variables

The initializers created by the `[try_][pin_]init!` macros utilize the
guard pattern to drop already initialized fields, when initialization
fails mid-way. These guards are generated to have the same name as the
field that they handle. To prevent namespacing issues [1] when the
field name is the same as e.g. a constant name, add `__` as a prefix
and `_guard` as the suffix.

[ Gary says:

   "Here's the simplified example:

    ```
    macro_rules! f {
        () => {
            let a = 1;
            let _: u32 = a;
        }
    }

    const a: u64 = 1;

    fn main() {
        f!();
    }
    ```

    The `a` in `f` have a different hygiene so normally it is scoped to the
    macro expansion and wouldn't escape. Interestingly a constant is still
    preferred despite the hygiene so constants escaped into the macro,
    leading to the error."

  - Miguel ]

Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/rust-for-linux/1e8a2a1f-abbf-44ba-8344-705a9cbb1627@proton.me/ [1]
Link: https://lore.kernel.org/r/20240403194321.88716-1-benno.lossin@proton.me
[ Added Benno's link and Gary's simplified example. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Benno Lossin 2024-04-03 19:43:37 +00:00 committed by Miguel Ojeda
parent a0a4e17013
commit 9218cf826f

View File

@ -250,7 +250,7 @@
//! // error type is `Infallible`) we will need to drop this field if there //! // 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 //! // is an error later. This `DropGuard` will drop the field when it gets
//! // dropped and has not yet been forgotten. //! // dropped and has not yet been forgotten.
//! let t = unsafe { //! let __t_guard = unsafe {
//! ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t)) //! ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t))
//! }; //! };
//! // Expansion of `x: 0,`: //! // Expansion of `x: 0,`:
@ -261,14 +261,14 @@
//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) }; //! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
//! } //! }
//! // We again create a `DropGuard`. //! // We again create a `DropGuard`.
//! let x = unsafe { //! let __x_guard = unsafe {
//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x)) //! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x))
//! }; //! };
//! // Since initialization has successfully completed, we can now forget //! // Since initialization has successfully completed, we can now forget
//! // the guards. This is not `mem::forget`, since we only have //! // the guards. This is not `mem::forget`, since we only have
//! // `&DropGuard`. //! // `&DropGuard`.
//! ::core::mem::forget(x); //! ::core::mem::forget(__x_guard);
//! ::core::mem::forget(t); //! ::core::mem::forget(__t_guard);
//! // Here we use the type checker to ensure that every field has been //! // 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 //! // initialized exactly once, since this is `if false` it will never get
//! // executed, but still type-checked. //! // executed, but still type-checked.
@ -461,16 +461,16 @@
//! { //! {
//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) }; //! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
//! } //! }
//! let a = unsafe { //! let __a_guard = unsafe {
//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a)) //! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a))
//! }; //! };
//! let init = Bar::new(36); //! let init = Bar::new(36);
//! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? }; //! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? };
//! let b = unsafe { //! let __b_guard = unsafe {
//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b)) //! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b))
//! }; //! };
//! ::core::mem::forget(b); //! ::core::mem::forget(__b_guard);
//! ::core::mem::forget(a); //! ::core::mem::forget(__a_guard);
//! #[allow(unreachable_code, clippy::diverging_sub_expression)] //! #[allow(unreachable_code, clippy::diverging_sub_expression)]
//! let _ = || { //! let _ = || {
//! unsafe { //! unsafe {
@ -1209,14 +1209,14 @@ macro_rules! __init_internal {
// We use `paste!` to create new hygiene for `$field`. // We use `paste!` to create new hygiene for `$field`.
::kernel::macros::paste! { ::kernel::macros::paste! {
// SAFETY: We forget the guard later when initialization has succeeded. // SAFETY: We forget the guard later when initialization has succeeded.
let [<$field>] = unsafe { let [< __ $field _guard >] = unsafe {
$crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field)) $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
}; };
$crate::__init_internal!(init_slot($use_data): $crate::__init_internal!(init_slot($use_data):
@data($data), @data($data),
@slot($slot), @slot($slot),
@guards([<$field>], $($guards,)*), @guards([< __ $field _guard >], $($guards,)*),
@munch_fields($($rest)*), @munch_fields($($rest)*),
); );
} }
@ -1240,14 +1240,14 @@ macro_rules! __init_internal {
// We use `paste!` to create new hygiene for `$field`. // We use `paste!` to create new hygiene for `$field`.
::kernel::macros::paste! { ::kernel::macros::paste! {
// SAFETY: We forget the guard later when initialization has succeeded. // SAFETY: We forget the guard later when initialization has succeeded.
let [<$field>] = unsafe { let [< __ $field _guard >] = unsafe {
$crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field)) $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
}; };
$crate::__init_internal!(init_slot(): $crate::__init_internal!(init_slot():
@data($data), @data($data),
@slot($slot), @slot($slot),
@guards([<$field>], $($guards,)*), @guards([< __ $field _guard >], $($guards,)*),
@munch_fields($($rest)*), @munch_fields($($rest)*),
); );
} }
@ -1272,14 +1272,14 @@ macro_rules! __init_internal {
// We use `paste!` to create new hygiene for `$field`. // We use `paste!` to create new hygiene for `$field`.
::kernel::macros::paste! { ::kernel::macros::paste! {
// SAFETY: We forget the guard later when initialization has succeeded. // SAFETY: We forget the guard later when initialization has succeeded.
let [<$field>] = unsafe { let [< __ $field _guard >] = unsafe {
$crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field)) $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
}; };
$crate::__init_internal!(init_slot($($use_data)?): $crate::__init_internal!(init_slot($($use_data)?):
@data($data), @data($data),
@slot($slot), @slot($slot),
@guards([<$field>], $($guards,)*), @guards([< __ $field _guard >], $($guards,)*),
@munch_fields($($rest)*), @munch_fields($($rest)*),
); );
} }