Skip to content

Commit bdda988

Browse files
committed
handle edge cases
1 parent 0a5ff9e commit bdda988

File tree

9 files changed

+134
-1
lines changed

9 files changed

+134
-1
lines changed

async-stream-impl/src/lib.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct AsyncStreamImpl {
1313
}
1414

1515
struct Scrub {
16+
is_xforming: bool,
1617
is_try: bool,
1718
yielder: syn::Ident,
1819
unit: Box<syn::Expr>,
@@ -39,6 +40,11 @@ impl Parse for AsyncStreamImpl {
3940

4041
impl VisitMut for Scrub {
4142
fn visit_expr_mut(&mut self, i: &mut syn::Expr) {
43+
if !self.is_xforming {
44+
syn::visit_mut::visit_expr_mut(self, i);
45+
return;
46+
}
47+
4248
match i {
4349
syn::Expr::Yield(yield_expr) => {
4450
self.num_yield += 1;
@@ -71,9 +77,23 @@ impl VisitMut for Scrub {
7177
}
7278
};
7379
}
74-
expr => syn::visit_mut::visit_expr_mut(self, expr),
80+
syn::Expr::Closure(_) |
81+
syn::Expr::Async(_) => {
82+
let prev = self.is_xforming;
83+
self.is_xforming = false;
84+
syn::visit_mut::visit_expr_mut(self, i);
85+
self.is_xforming = prev;
86+
}
87+
_ => syn::visit_mut::visit_expr_mut(self, i),
7588
}
7689
}
90+
91+
fn visit_item_mut(&mut self, i: &mut syn::Item) {
92+
let prev = self.is_xforming;
93+
self.is_xforming = false;
94+
syn::visit_mut::visit_item_mut(self, i);
95+
self.is_xforming = prev;
96+
}
7797
}
7898

7999
#[proc_macro_hack]
@@ -84,6 +104,7 @@ pub fn async_stream_impl(input: TokenStream) -> TokenStream {
84104
} = syn::parse_macro_input!(input as AsyncStreamImpl);
85105

86106
let mut scrub = Scrub {
107+
is_xforming: true,
87108
is_try: false,
88109
yielder,
89110
unit: syn::parse_quote!(()),
@@ -119,6 +140,7 @@ pub fn async_try_stream_impl(input: TokenStream) -> TokenStream {
119140
} = syn::parse_macro_input!(input as AsyncStreamImpl);
120141

121142
let mut scrub = Scrub {
143+
is_xforming: true,
122144
is_try: true,
123145
yielder,
124146
unit: syn::parse_quote!(()),

async-stream/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ proc-macro-hack = "0.5.8"
1313
tokio = "=0.2.0-alpha.1"
1414
tokio-test = "=0.2.0-alpha.1"
1515
futures-util-preview = "=0.3.0-alpha.17"
16+
trybuild = "1.0"

async-stream/tests/stream.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,28 @@ async fn borrow_self() {
123123

124124
assert_eq!(Some("hello"), s.next().await);
125125
}
126+
127+
#[tokio::test]
128+
async fn stream_in_stream() {
129+
let s = stream! {
130+
let s = stream! {
131+
for i in 0..3 {
132+
yield i;
133+
}
134+
};
135+
136+
pin_mut!(s);
137+
while let Some(v) = s.next().await {
138+
yield v;
139+
}
140+
};
141+
142+
let values: Vec<_> = s.collect().await;
143+
assert_eq!(3, values.len());
144+
}
145+
146+
#[test]
147+
fn test() {
148+
let t = trybuild::TestCases::new();
149+
t.compile_fail("tests/ui/*.rs");
150+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(async_await)]
2+
3+
use async_stream::stream;
4+
5+
fn main() {
6+
stream! {
7+
let f = async {
8+
yield 123;
9+
};
10+
11+
let v = f.await;
12+
};
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0658]: yield syntax is experimental
2+
--> $DIR/yield_in_async.rs:8:13
3+
|
4+
8 | yield 123;
5+
| ^^^^^^^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/43122
8+
= help: add `#![feature(generators)]` to the crate attributes to enable
9+
10+
error[E0727]: `async` generators are not yet supported
11+
--> $DIR/yield_in_async.rs:8:13
12+
|
13+
8 | yield 123;
14+
| ^^^^^^^^^
15+
16+
For more information about this error, try `rustc --explain E0658`.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(async_await)]
2+
3+
use async_stream::stream;
4+
5+
fn main() {
6+
stream! {
7+
Ok("value")
8+
.and_then(|v| {
9+
yield v;
10+
Ok(())
11+
});
12+
};
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0658]: yield syntax is experimental
2+
--> $DIR/yield_in_closure.rs:9:17
3+
|
4+
9 | yield v;
5+
| ^^^^^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/43122
8+
= help: add `#![feature(generators)]` to the crate attributes to enable
9+
10+
error[E0628]: generators cannot have explicit arguments
11+
--> $DIR/yield_in_closure.rs:8:23
12+
|
13+
8 | .and_then(|v| {
14+
| ^^^
15+
16+
For more information about this error, try `rustc --explain E0658`.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(async_await)]
2+
3+
use async_stream::stream;
4+
5+
fn main() {
6+
stream! {
7+
fn foo() {
8+
yield "hello";
9+
}
10+
};
11+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0658]: yield syntax is experimental
2+
--> $DIR/yield_in_nested_fn.rs:8:13
3+
|
4+
8 | yield "hello";
5+
| ^^^^^^^^^^^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/43122
8+
= help: add `#![feature(generators)]` to the crate attributes to enable
9+
10+
error[E0627]: yield statement outside of generator literal
11+
--> $DIR/yield_in_nested_fn.rs:8:13
12+
|
13+
8 | yield "hello";
14+
| ^^^^^^^^^^^^^
15+
16+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)