Commit 9218cf82 authored by Benno Lossin's avatar Benno Lossin Committed by Miguel Ojeda
Browse files

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: default avatarBenno Lossin <benno.lossin@proton.me>
Reviewed-by: default avatarBoqun Feng <boqun.feng@gmail.com>
Reviewed-by: default avatarAlice 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: default avatarMiguel Ojeda <ojeda@kernel.org>
parent a0a4e170
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -250,7 +250,7 @@
//!                     // 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 {
//!                     let __t_guard = unsafe {
//!                         ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t))
//!                     };
//!                     // Expansion of `x: 0,`:
@@ -261,14 +261,14 @@
//!                         unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
//!                     }
//!                     // We again create a `DropGuard`.
//!                     let x = unsafe {
//!                     let __x_guard = 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);
//!                     ::core::mem::forget(__x_guard);
//!                     ::core::mem::forget(__t_guard);
//!                     // 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.
@@ -461,16 +461,16 @@
//!             {
//!                 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))
//!             };
//!             let init = Bar::new(36);
//!             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))
//!             };
//!             ::core::mem::forget(b);
//!             ::core::mem::forget(a);
//!             ::core::mem::forget(__b_guard);
//!             ::core::mem::forget(__a_guard);
//!             #[allow(unreachable_code, clippy::diverging_sub_expression)]
//!             let _ = || {
//!                 unsafe {
@@ -1209,14 +1209,14 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
        // We use `paste!` to create new hygiene for `$field`.
        ::kernel::macros::paste! {
            // 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!(init_slot($use_data):
                @data($data),
                @slot($slot),
                @guards([<$field>], $($guards,)*),
                @guards([< __ $field _guard >], $($guards,)*),
                @munch_fields($($rest)*),
            );
        }
@@ -1240,14 +1240,14 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
        // We use `paste!` to create new hygiene for `$field`.
        ::kernel::macros::paste! {
            // 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!(init_slot():
                @data($data),
                @slot($slot),
                @guards([<$field>], $($guards,)*),
                @guards([< __ $field _guard >], $($guards,)*),
                @munch_fields($($rest)*),
            );
        }
@@ -1272,14 +1272,14 @@ fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
        // We use `paste!` to create new hygiene for `$field`.
        ::kernel::macros::paste! {
            // 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!(init_slot($($use_data)?):
                @data($data),
                @slot($slot),
                @guards([<$field>], $($guards,)*),
                @guards([< __ $field _guard >], $($guards,)*),
                @munch_fields($($rest)*),
            );
        }