Skip to content

Commit ab465ec

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

File tree

3 files changed

+103
-11
lines changed

3 files changed

+103
-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: 100 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,91 @@
1-
use pin_init::{try_init, Init};
1+
#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
2+
use core::cell::Cell;
3+
use pin_init::*;
24

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

791
fn foo() -> bool {
@@ -13,19 +97,26 @@ fn bar() -> bool {
1397
}
1498

1599
impl Foo {
16-
pub fn new() -> impl Init<Self, ()> {
100+
pub fn late_error_new() -> impl Init<Self, Error> {
17101
try_init!(Self {
18102
_: {
19103
if foo() {
20-
return Err(());
104+
return Err(Error);
21105
}
22106
},
23-
x: 0,
107+
a: 0,
24108
_: {
25109
if bar() {
26-
return Err(());
110+
return Err(Error);
27111
}
28-
}
29-
}? ())
112+
},
113+
b: 0,
114+
}? Error)
30115
}
31116
}
117+
118+
#[test]
119+
fn late_error() {
120+
stack_try_pin_init!(let foo = Foo::late_error_new());
121+
assert!(foo.is_err());
122+
}

0 commit comments

Comments
 (0)