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:
parent
a0a4e17013
commit
9218cf826f
@ -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)*),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user