Skip to content

Commit 7ecda0c

Browse files
committed
Expose bindings in _: {} blocks
Signed-off-by: Matthew Maurer <[email protected]>
1 parent 871cf88 commit 7ecda0c

File tree

3 files changed

+102
-11
lines changed

3 files changed

+102
-11
lines changed

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,8 @@ macro_rules! stack_try_pin_init {
741741
/// the following modifications is expected:
742742
/// - Fields that you want to initialize in-place have to use `<-` instead of `:`.
743743
/// - You can use `_: { /* run any user-code here */ },` anywhere where you can place fields in
744-
/// order to run arbitrary code.
744+
/// order to run arbitrary code. Bindings present here will be visible to field initializers that
745+
/// follow.
745746
/// - In front of the initializer you can write `&this in` to have access to a [`NonNull<Self>`]
746747
/// pointer named `this` inside of the initializer.
747748
/// - Using struct update syntax one can place `..Zeroable::init_zeroed()` at the very end of the

src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1290,7 +1290,7 @@ macro_rules! __init_internal {
12901290
// arbitrary code block
12911291
@munch_fields(_: { $($code:tt)* }, $($rest:tt)*),
12921292
) => {
1293-
{ $($code)* }
1293+
$($code)*;
12941294
$crate::__init_internal!(init_slot($($use_data)?):
12951295
@data($data),
12961296
@slot($slot),

tests/underscore.rs

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,90 @@
1-
use pin_init::{try_init, Init};
1+
use core::cell::Cell;
2+
use pin_init::*;
23

3-
pub struct Foo {
4-
x: u64,
4+
#[derive(Debug)]
5+
struct Error;
6+
7+
#[pin_data]
8+
#[derive(Debug)]
9+
struct Foo {
10+
a: usize,
11+
b: usize,
12+
}
13+
14+
struct Bar;
15+
16+
impl Bar {
17+
fn new() -> Result<Self, Error> {
18+
Ok(Self)
19+
}
20+
fn make_a(&self) -> usize {
21+
10
22+
}
23+
fn make_b(&self) -> usize {
24+
20
25+
}
26+
}
27+
28+
fn error(_bar: &Bar) -> Result<(), Error> {
29+
Err(Error)
30+
}
31+
32+
fn ok(_bar: &Bar) -> Result<(), Error> {
33+
Ok(())
34+
}
35+
36+
#[test]
37+
fn delay() {
38+
let state = &Cell::new(3);
39+
let init = pin_init!(Foo {
40+
_: {
41+
let x = state.get();
42+
let y = x + 1;
43+
},
44+
a: x,
45+
b: y,
46+
});
47+
state.set(42);
48+
stack_pin_init!(let foo = init);
49+
assert_eq!(foo.a, 42);
50+
assert_eq!(foo.b, 43);
51+
}
52+
53+
#[test]
54+
fn error_user() {
55+
let bar = Bar;
56+
stack_try_pin_init!(let foo = try_pin_init!(Foo {
57+
_: { error(&bar)? },
58+
a: 1,
59+
b: 2,
60+
}? Error));
61+
62+
assert!(foo.is_err());
63+
}
64+
65+
#[test]
66+
fn ok_user() {
67+
let bar = Bar;
68+
stack_try_pin_init!(let foo = try_pin_init!(Foo {
69+
_: { ok(&bar)? },
70+
a: 1,
71+
b: 2,
72+
}? Error));
73+
74+
assert_eq!(foo.unwrap().a, 1);
75+
}
76+
77+
#[test]
78+
fn split() {
79+
stack_try_pin_init!(let foo = try_pin_init!(Foo {
80+
_: { let bar = Bar::new()? },
81+
a: bar.make_a(),
82+
b: bar.make_b(),
83+
}? Error));
84+
85+
let foo = foo.unwrap();
86+
assert_eq!(foo.a, 10);
87+
assert_eq!(foo.b, 20);
588
}
689

790
fn foo() -> bool {
@@ -13,19 +96,26 @@ fn bar() -> bool {
1396
}
1497

1598
impl Foo {
16-
pub fn new() -> impl Init<Self, ()> {
99+
pub fn late_error_new() -> impl Init<Self, Error> {
17100
try_init!(Self {
18101
_: {
19102
if foo() {
20-
return Err(());
103+
return Err(Error);
21104
}
22105
},
23-
x: 0,
106+
a: 0,
24107
_: {
25108
if bar() {
26-
return Err(());
109+
return Err(Error);
27110
}
28-
}
29-
}? ())
111+
},
112+
b: 0,
113+
}? Error)
30114
}
31115
}
116+
117+
#[test]
118+
fn late_error() {
119+
stack_try_pin_init!(let foo = Foo::late_error_new());
120+
assert!(foo.is_err());
121+
}

0 commit comments

Comments
 (0)