Skip to content

Commit 8c8ac52

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

File tree

3 files changed

+104
-11
lines changed

3 files changed

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

792
fn foo() -> bool {
@@ -13,19 +98,26 @@ fn bar() -> bool {
1398
}
1499

15100
impl Foo {
16-
pub fn new() -> impl Init<Self, ()> {
101+
pub fn late_error_new() -> impl Init<Self, Error> {
17102
try_init!(Self {
18103
_: {
19104
if foo() {
20-
return Err(());
105+
return Err(Error);
21106
}
22107
},
23-
x: 0,
108+
a: 0,
24109
_: {
25110
if bar() {
26-
return Err(());
111+
return Err(Error);
27112
}
28-
}
29-
}? ())
113+
},
114+
b: 0,
115+
}? Error)
30116
}
31117
}
118+
119+
#[test]
120+
fn late_error() {
121+
stack_try_pin_init!(let foo = Foo::late_error_new());
122+
assert!(foo.is_err());
123+
}

0 commit comments

Comments
 (0)