Skip to content

Commit 2880a9b

Browse files
committed
add code blocks to [try_][pin_]init! macros
Allow writing `_: { /* any number of statements */ }` in initializers to run arbitrary code during initialization. try_init!(MyStruct { _: { if check_something() { return Err(MyError); } }, foo: Foo::new(val), _: { println!("successfully initialized `MyStruct`"); }, }) Signed-off-by: Benno Lossin <lossin@kernel.org>
1 parent 88e63c3 commit 2880a9b

File tree

4 files changed

+38
-1
lines changed

4 files changed

+38
-1
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- Add initializer code blocks to `[try_][pin_]init!` macros: make initializer
13+
macros accept any number of `_: {/* arbitrary code */},` & make them run the
14+
code at that point.
15+
1016
## [0.0.10] - 2025-08-19
1117

1218
### Added

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,8 @@ macro_rules! stack_try_pin_init {
740740
/// As already mentioned in the examples above, inside of `pin_init!` a `struct` initializer with
741741
/// the following modifications is expected:
742742
/// - Fields that you want to initialize in-place have to use `<-` instead of `:`.
743+
/// - You can use `_: { /* run any user-code here */ },` anywhere where you can place fields in
744+
/// order to run arbitrary code.
743745
/// - In front of the initializer you can write `&this in` to have access to a [`NonNull<Self>`]
744746
/// pointer named `this` inside of the initializer.
745747
/// - Using struct update syntax one can place `..Zeroable::init_zeroed()` at the very end of the

src/macros.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,21 @@ macro_rules! __init_internal {
12021202
// have been initialized. Therefore we can now dismiss the guards by forgetting them.
12031203
$(::core::mem::forget($guards);)*
12041204
};
1205+
(init_slot($($use_data:ident)?):
1206+
@data($data:ident),
1207+
@slot($slot:ident),
1208+
@guards($($guards:ident,)*),
1209+
// arbitrary code block
1210+
@munch_fields(_: { $($code:tt)* }, $($rest:tt)*),
1211+
) => {
1212+
{ $($code)* }
1213+
$crate::__init_internal!(init_slot($($use_data)?):
1214+
@data($data),
1215+
@slot($slot),
1216+
@guards($($guards,)*),
1217+
@munch_fields($($rest)*),
1218+
);
1219+
};
12051220
(init_slot($use_data:ident): // `use_data` is present, so we use the `data` to init fields.
12061221
@data($data:ident),
12071222
@slot($slot:ident),
@@ -1351,6 +1366,20 @@ macro_rules! __init_internal {
13511366
);
13521367
}
13531368
};
1369+
(make_initializer:
1370+
@slot($slot:ident),
1371+
@type_name($t:path),
1372+
@munch_fields(_: { $($code:tt)* }, $($rest:tt)*),
1373+
@acc($($acc:tt)*),
1374+
) => {
1375+
// code blocks are ignored for the initializer check
1376+
$crate::__init_internal!(make_initializer:
1377+
@slot($slot),
1378+
@type_name($t),
1379+
@munch_fields($($rest)*),
1380+
@acc($($acc)*),
1381+
);
1382+
};
13541383
(make_initializer:
13551384
@slot($slot:ident),
13561385
@type_name($t:path),

tests/ui/compile-fail/init/wrong_generics2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ help: you might have forgotten to add the struct literal inside the block
1212
--> src/macros.rs
1313
|
1414
~ ::core::ptr::write($slot, $t { SomeStruct {
15-
|9 $($acc)*
15+
|4 $($acc)*
1616
~ } });
1717
|
1818

0 commit comments

Comments
 (0)