rust: init: make initializer values inaccessible after initializing
Previously the init macros would create a local variable with the name and hygiene of the field that is being initialized to store the value of the field. This would override any user defined variables. For example: ``` struct Foo { a: usize, b: usize, } let a = 10; let foo = init!(Foo{ a: a + 1, // This creates a local variable named `a`. b: a, // This refers to that variable! }); let foo = Box::init!(foo)?; assert_eq!(foo.a, 11); assert_eq!(foo.b, 11); ``` This patch changes this behavior, so the above code would panic at the last assertion, since `b` would have value 10. Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <benno.lossin@proton.me> Link: https://lore.kernel.org/r/20230814084602.25699-7-benno.lossin@proton.me Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Родитель
b9b88be046
Коммит
92fd540d62
|
@ -1075,13 +1075,13 @@ macro_rules! __init_internal {
|
|||
// In-place initialization syntax.
|
||||
@munch_fields($field:ident <- $val:expr, $($rest:tt)*),
|
||||
) => {
|
||||
let $field = $val;
|
||||
let init = $val;
|
||||
// Call the initializer.
|
||||
//
|
||||
// SAFETY: `slot` is valid, because we are inside of an initializer closure, we
|
||||
// return when an error/panic occurs.
|
||||
// We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
|
||||
unsafe { $data.$field(::core::ptr::addr_of_mut!((*$slot).$field), $field)? };
|
||||
unsafe { $data.$field(::core::ptr::addr_of_mut!((*$slot).$field), init)? };
|
||||
// Create the drop guard:
|
||||
//
|
||||
// We rely on macro hygiene to make it impossible for users to access this local variable.
|
||||
|
@ -1107,12 +1107,12 @@ macro_rules! __init_internal {
|
|||
// In-place initialization syntax.
|
||||
@munch_fields($field:ident <- $val:expr, $($rest:tt)*),
|
||||
) => {
|
||||
let $field = $val;
|
||||
let init = $val;
|
||||
// Call the initializer.
|
||||
//
|
||||
// SAFETY: `slot` is valid, because we are inside of an initializer closure, we
|
||||
// return when an error/panic occurs.
|
||||
unsafe { $crate::init::Init::__init($field, ::core::ptr::addr_of_mut!((*$slot).$field))? };
|
||||
unsafe { $crate::init::Init::__init(init, ::core::ptr::addr_of_mut!((*$slot).$field))? };
|
||||
// Create the drop guard:
|
||||
//
|
||||
// We rely on macro hygiene to make it impossible for users to access this local variable.
|
||||
|
@ -1138,11 +1138,13 @@ macro_rules! __init_internal {
|
|||
// Init by-value.
|
||||
@munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
|
||||
) => {
|
||||
$(let $field = $val;)?
|
||||
// Initialize the field.
|
||||
//
|
||||
// SAFETY: The memory at `slot` is uninitialized.
|
||||
unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) };
|
||||
{
|
||||
$(let $field = $val;)?
|
||||
// Initialize the field.
|
||||
//
|
||||
// SAFETY: The memory at `slot` is uninitialized.
|
||||
unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) };
|
||||
}
|
||||
// Create the drop guard:
|
||||
//
|
||||
// We rely on macro hygiene to make it impossible for users to access this local variable.
|
||||
|
|
Загрузка…
Ссылка в новой задаче