+1
Cargo.lock
+1
Cargo.lock
+2
-1
futures-combinators/src/join.rs
+2
-1
futures-combinators/src/join.rs
+2
-1
futures-combinators/src/race.rs
+2
-1
futures-combinators/src/race.rs
+1
-41
futures-combinators/src/wake.rs
+1
-41
futures-combinators/src/wake.rs
···
1
-
use std::{
2
-
array, cell::Cell, marker::PhantomPinned, pin::Pin, ptr::NonNull,
3
-
task::Poll,
4
-
};
1
+
use std::{array, cell::Cell, marker::PhantomPinned, pin::Pin, ptr::NonNull};
5
2
6
3
use futures_compat::{LocalWaker, WakePtr};
7
4
use futures_core::Wake;
···
115
112
// }
116
113
// }
117
114
// }
118
-
119
-
pub struct PollFn<F, T>(F)
120
-
where
121
-
F: FnMut(&LocalWaker) -> Poll<T>;
122
-
123
-
impl<F, T> futures_core::Future<LocalWaker> for PollFn<F, T>
124
-
where
125
-
F: FnMut(&LocalWaker) -> Poll<T>,
126
-
{
127
-
type Output = T;
128
-
129
-
fn poll(
130
-
self: Pin<&mut Self>,
131
-
waker: Pin<&LocalWaker>,
132
-
) -> Poll<Self::Output> {
133
-
(unsafe { &mut self.get_unchecked_mut().0 })(&waker)
134
-
}
135
-
}
136
-
137
-
pub fn poll_fn<F, T>(f: F) -> impl futures_core::Future<LocalWaker, Output = T>
138
-
where
139
-
F: FnMut(&LocalWaker) -> Poll<T>,
140
-
{
141
-
PollFn(f)
142
-
}
143
-
144
-
pub struct DummyWaker;
145
-
146
-
impl Wake for DummyWaker {
147
-
fn wake(&self) {
148
-
dbg!("awake!");
149
-
}
150
-
}
151
-
152
-
pub fn dummy_guard() -> ValueGuard<WakePtr> {
153
-
ValueGuard::new(NonNull::new(&mut DummyWaker as *mut dyn Wake))
154
-
}
+2
-13
futures-compat/src/lib.rs
+2
-13
futures-compat/src/lib.rs
···
116
116
}
117
117
}
118
118
119
-
// impl<F> core::future::Future for F
120
-
// where
121
-
// F: for<'a> futures_core::Future<Context<'a>>,
122
-
// {
123
-
// type Output = F::Output;
124
-
125
-
// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
126
-
// self.poll(cx.waker())
127
-
// }
128
-
// }
129
-
130
119
#[cfg(test)]
131
120
mod test {
132
121
use std::pin;
···
149
138
let waker = unsafe { guard_to_waker(guard.as_ref()) };
150
139
let guard = unsafe { waker_to_guard(&waker) };
151
140
assert_eq!(
152
-
guard.get().unwrap().as_ptr(),
153
-
&dummy as *const dyn Wake as *mut dyn Wake
141
+
guard.get().unwrap().as_ptr() as *const () as usize,
142
+
&dummy as *const _ as *const () as usize
154
143
);
155
144
}
156
145
}
+72
-70
futures-derive/src/lib.rs
+72
-70
futures-derive/src/lib.rs
···
1
1
use proc_macro::TokenStream;
2
2
use quote::{ToTokens, quote};
3
3
use syn::{
4
-
Expr, ExprAwait, FnArg, GenericArgument, ItemFn, ReturnType,
5
-
parse_macro_input, parse_quote, parse2, visit_mut::VisitMut,
4
+
Expr, ExprAwait, ItemFn, ReturnType, parse_macro_input, parse_quote,
5
+
parse2, visit_mut::VisitMut,
6
6
};
7
7
8
8
/// Takes async fn that returns anonymous `Future` impl.
9
9
/// Generates fn that returns `UnscopedFutureWrapper` wrapper for the the anonymous `Future` impl.
10
10
///
11
-
/// ```rust
12
-
/// fn my_func<'a, 'b>(a: &'a A, b: &'b B) -> impl ScopedFuture<'a + 'b, Output = T> + 'a + 'b {
11
+
/// ```rust,ignore
12
+
/// fn my_func<'a, 'b>(a: &'a A, b: &'b B) -> impl ScopedFuture<LifetimeGuard, Output = Output> {
13
13
/// let output = async move { [body] } // compilers turns this into -> impl Future<Output = T> + 'a + 'b
14
-
/// unsafe { UnscopedFutureWrapper::from_future(output) }
14
+
/// unsafe { futures_compat::std_future_to_bespoke(output) }
15
15
/// }
16
16
/// ```
17
17
///
···
22
22
/// to actually implement this (capture all lifetimes) we use `ScopedFuture<'_> + '_` so the compiler can infer
23
23
/// lifetimes from the anonymous future impl returned by the actual inner async fn
24
24
#[proc_macro_attribute]
25
-
pub fn async_scoped(_: TokenStream, item: TokenStream) -> TokenStream {
25
+
pub fn async_function(_: TokenStream, item: TokenStream) -> TokenStream {
26
26
let mut item_fn = parse_macro_input!(item as ItemFn);
27
27
// Wraps *every* async expression within the function block with
28
-
// `ScopedFutureWrapper`, allowing them to be treated as regular `Future`
28
+
// `BespokeFutureWrapper`, allowing them to be treated as regular `Future`
29
29
// impls.
30
30
//
31
31
// This will cause a compiler error if any expression being awaited is not
32
32
// a `ScopedFuture`, which is intentional because the `Future` and
33
33
// `ScopedFuture` systems are incompatible.
34
-
ScopedFutureWrappingVisitor.visit_item_fn_mut(&mut item_fn);
34
+
BespokeFutureWrappingVisitor.visit_item_fn_mut(&mut item_fn);
35
35
36
36
// disable async since it is moved to the block
37
37
item_fn.sig.asyncness = None;
···
41
41
*item_fn.block = parse_quote! {
42
42
{
43
43
let future = async move #block;
44
-
unsafe { futures_compat::UnscopedFutureWrapper::from_future(future) }
44
+
unsafe { futures_compat::std_future_to_bespoke(future) }
45
45
}
46
46
};
47
47
48
-
let output = match &item_fn.sig.output {
48
+
let output_type = match &item_fn.sig.output {
49
49
ReturnType::Default => quote! { () },
50
50
ReturnType::Type(_, ty) => quote! { #ty },
51
51
};
52
52
53
-
let has_lifetime_dependency =
54
-
item_fn.sig.inputs.iter().any(|param| match param {
55
-
FnArg::Receiver(receiver) => receiver.reference.is_some(),
56
-
FnArg::Typed(pat) => has_lifetime_dependency(&pat.ty),
57
-
});
53
+
item_fn.sig.output = parse_quote! { -> impl futures_core::Future<LocalWaker, Output = #output_type> };
58
54
59
-
// set outer fn output to ScopedFuture<'_/'static, Output = #output>
60
-
item_fn.sig.output = if has_lifetime_dependency {
61
-
parse_quote! { -> impl futures_core::ScopedFuture<'_, Output = #output> + '_ }
62
-
} else {
63
-
parse_quote! { -> impl futures_core::ScopedFuture<'static, Output = #output> }
64
-
};
55
+
// let has_lifetime_dependency =
56
+
// item_fn.sig.inputs.iter().any(|param| match param {
57
+
// FnArg::Receiver(receiver) => receiver.reference.is_some(),
58
+
// FnArg::Typed(pat) => has_lifetime_dependency(&pat.ty),
59
+
// });
60
+
61
+
// // set outer fn output to ScopedFuture<'_/'static, Output = #output>
62
+
// item_fn.sig.output = if has_lifetime_dependency {
63
+
// parse_quote! { -> impl futures_core::ScopedFuture<'_, Output = #output> + '_ }
64
+
// } else {
65
+
// parse_quote! { -> impl futures_core::ScopedFuture<'static, Output = #output> }
66
+
// };
65
67
66
68
item_fn.to_token_stream().into()
67
69
}
···
72
74
/// Takes async fn that returns anonymous `Future` impl.
73
75
/// Generates fn that returns `UnscopedFutureWrapper` wrapper for the the anonymous `Future` impl.
74
76
///
75
-
/// ```rust
77
+
/// ```rust,ignore
76
78
/// fn [original name]<'a, 'b>(a: &'a A, b: &'b B) -> impl ScopedFuture<'a + 'b, Output = T> + 'a + 'b {
77
79
/// async fn [__inner]<'a, 'b>(a: &'a A, b: &'b B) -> T { [body] } // compilers turns this into -> impl Future<Output = T> + 'a + 'b
78
80
/// unsafe { UnscopedFutureWrapper::from_future(__inner()) }
···
123
125
///
124
126
/// This generates a modified block of the form:
125
127
///
126
-
/// ```rust
128
+
/// ```rust,ignore
127
129
/// {
128
130
/// let output = async { <original block, mapped to convert all `ScopedFuture` to `Future`> };
129
131
/// unsafe { futures_compat::UnscopedFutureWrapper::from_future(output) }
130
132
/// }
131
133
/// ```
132
134
#[proc_macro]
133
-
pub fn block(input: TokenStream) -> TokenStream {
135
+
pub fn async_block(input: TokenStream) -> TokenStream {
134
136
// block is formed { **expr/stmt }, so we need to surround the inputs in {}
135
137
let input = proc_macro2::TokenStream::from(input);
136
138
let block_input = quote! { { #input } };
137
139
138
140
let mut block = parse2(block_input).expect("Failed to parse as block.");
139
141
140
-
ScopedFutureWrappingVisitor.visit_block_mut(&mut block);
142
+
BespokeFutureWrappingVisitor.visit_block_mut(&mut block);
141
143
142
144
quote! {
143
145
{
144
146
let output = async #block;
145
-
unsafe { futures_compat::UnscopedFutureWrapper::from_future(output) }
147
+
unsafe { futures_compat::std_future_to_bespoke(output) }
146
148
}
147
149
}
148
150
.into()
···
150
152
151
153
/// Determines if typed pattern contains a reference or dependency on a
152
154
/// lifetime (used for deciding between '_ and 'static ScopedFuture).
153
-
fn has_lifetime_dependency(ty: &syn::Type) -> bool {
154
-
match ty {
155
-
syn::Type::Reference(_) => true,
156
-
syn::Type::Path(type_path) => {
157
-
type_path.path.segments.iter().any(|segment| {
158
-
if let syn::PathArguments::AngleBracketed(args) =
159
-
&segment.arguments
160
-
{
161
-
args.args.iter().any(|arg| match arg {
162
-
GenericArgument::Type(ty) => {
163
-
has_lifetime_dependency(ty)
164
-
}
165
-
syn::GenericArgument::Lifetime(_) => true,
166
-
_ => false,
167
-
})
168
-
} else {
169
-
false
170
-
}
171
-
})
172
-
}
173
-
syn::Type::Tuple(tuple) => {
174
-
tuple.elems.iter().any(has_lifetime_dependency)
175
-
}
176
-
syn::Type::Slice(slice) => has_lifetime_dependency(&slice.elem),
177
-
syn::Type::Array(array) => has_lifetime_dependency(&array.elem),
178
-
syn::Type::Ptr(ptr) => has_lifetime_dependency(&ptr.elem),
179
-
syn::Type::Group(group) => has_lifetime_dependency(&group.elem),
180
-
syn::Type::Paren(paren) => has_lifetime_dependency(&paren.elem),
181
-
syn::Type::BareFn(bare_fn) => {
182
-
bare_fn
183
-
.inputs
184
-
.iter()
185
-
.any(|input| has_lifetime_dependency(&input.ty))
186
-
|| match &bare_fn.output {
187
-
ReturnType::Default => false,
188
-
ReturnType::Type(_, ty) => has_lifetime_dependency(ty),
189
-
}
190
-
}
155
+
// fn has_lifetime_dependency(ty: &syn::Type) -> bool {
156
+
// match ty {
157
+
// syn::Type::Reference(_) => true,
158
+
// syn::Type::Path(type_path) => {
159
+
// type_path.path.segments.iter().any(|segment| {
160
+
// if let syn::PathArguments::AngleBracketed(args) =
161
+
// &segment.arguments
162
+
// {
163
+
// args.args.iter().any(|arg| match arg {
164
+
// GenericArgument::Type(ty) => {
165
+
// has_lifetime_dependency(ty)
166
+
// }
167
+
// syn::GenericArgument::Lifetime(_) => true,
168
+
// _ => false,
169
+
// })
170
+
// } else {
171
+
// false
172
+
// }
173
+
// })
174
+
// }
175
+
// syn::Type::Tuple(tuple) => {
176
+
// tuple.elems.iter().any(has_lifetime_dependency)
177
+
// }
178
+
// syn::Type::Slice(slice) => has_lifetime_dependency(&slice.elem),
179
+
// syn::Type::Array(array) => has_lifetime_dependency(&array.elem),
180
+
// syn::Type::Ptr(ptr) => has_lifetime_dependency(&ptr.elem),
181
+
// syn::Type::Group(group) => has_lifetime_dependency(&group.elem),
182
+
// syn::Type::Paren(paren) => has_lifetime_dependency(&paren.elem),
183
+
// syn::Type::BareFn(bare_fn) => {
184
+
// bare_fn
185
+
// .inputs
186
+
// .iter()
187
+
// .any(|input| has_lifetime_dependency(&input.ty))
188
+
// || match &bare_fn.output {
189
+
// ReturnType::Default => false,
190
+
// ReturnType::Type(_, ty) => has_lifetime_dependency(ty),
191
+
// }
192
+
// }
191
193
192
-
_ => false,
193
-
}
194
-
}
194
+
// _ => false,
195
+
// }
196
+
// }
195
197
196
198
/// Uses the `syn::visit_mut` api to wrap every `.await` expression in
197
199
/// `ScopedFutureWrapper`.
198
-
struct ScopedFutureWrappingVisitor;
200
+
struct BespokeFutureWrappingVisitor;
199
201
200
-
impl VisitMut for ScopedFutureWrappingVisitor {
202
+
impl VisitMut for BespokeFutureWrappingVisitor {
201
203
fn visit_expr_mut(&mut self, expr: &mut syn::Expr) {
202
204
if let Expr::Await(ExprAwait { attrs, base, .. }) = expr {
203
205
*expr = syn::parse_quote! {
204
-
unsafe { futures_compat::ScopedFutureWrapper::from_scoped(#(#attrs)* #base) }.await
206
+
unsafe { futures_compat::bespoke_future_to_std(#(#attrs)* #base) }.await
205
207
};
206
208
}
207
209
+17
futures-util/src/block_on.rs
+17
futures-util/src/block_on.rs
···
1
+
use std::{
2
+
pin::{self, Pin},
3
+
task::Poll,
4
+
};
5
+
6
+
use crate::{LocalWaker, dummy_guard};
7
+
8
+
pub fn block_on<F: futures_core::Future<LocalWaker>>(
9
+
mut f: Pin<&mut F>,
10
+
) -> F::Output {
11
+
let dummy_guard = pin::pin!(dummy_guard());
12
+
loop {
13
+
if let Poll::Ready(out) = f.as_mut().poll(dummy_guard.as_ref()) {
14
+
return out;
15
+
}
16
+
}
17
+
}
+39
-1
futures-util/src/lib.rs
+39
-1
futures-util/src/lib.rs
···
1
-
use std::ptr::NonNull;
1
+
use std::{pin::Pin, ptr::NonNull, task::Poll};
2
2
3
3
use futures_core::{Future, Wake};
4
4
use lifetime_guard::{atomic_guard::AtomicValueGuard, guard::ValueGuard};
5
5
6
+
pub mod block_on;
6
7
pub mod maybe_done;
7
8
8
9
pub type WakePtr = Option<NonNull<dyn Wake>>;
···
15
16
{
16
17
future
17
18
}
19
+
20
+
pub struct PollFn<F, T>(F)
21
+
where
22
+
F: FnMut(&LocalWaker) -> Poll<T>;
23
+
24
+
impl<F, T> futures_core::Future<LocalWaker> for PollFn<F, T>
25
+
where
26
+
F: FnMut(&LocalWaker) -> Poll<T>,
27
+
{
28
+
type Output = T;
29
+
30
+
fn poll(
31
+
self: Pin<&mut Self>,
32
+
waker: Pin<&LocalWaker>,
33
+
) -> Poll<Self::Output> {
34
+
(unsafe { &mut self.get_unchecked_mut().0 })(&waker)
35
+
}
36
+
}
37
+
38
+
pub fn poll_fn<F, T>(f: F) -> impl futures_core::Future<LocalWaker, Output = T>
39
+
where
40
+
F: FnMut(&LocalWaker) -> Poll<T>,
41
+
{
42
+
PollFn(f)
43
+
}
44
+
45
+
pub struct DummyWaker;
46
+
47
+
impl Wake for DummyWaker {
48
+
fn wake(&self) {
49
+
dbg!("awake!");
50
+
}
51
+
}
52
+
53
+
pub fn dummy_guard() -> ValueGuard<WakePtr> {
54
+
ValueGuard::new(NonNull::new(&mut DummyWaker as *mut dyn Wake))
55
+
}
+7
-20
futures-util/src/maybe_done.rs
+7
-20
futures-util/src/maybe_done.rs
···
15
15
///
16
16
/// This is created by the [`maybe_done()`] function.
17
17
#[derive(Debug)]
18
-
pub enum MaybeDone<Fut: Future<LocalWaker>> {
18
+
pub enum MaybeDone<Fut: futures_core::Future<LocalWaker>> {
19
19
/// A not-yet-completed future
20
20
Future(/* #[pin] */ Fut),
21
21
/// The output of the completed future
···
28
28
impl<Fut: Future<LocalWaker> + Unpin> Unpin for MaybeDone<Fut> {}
29
29
30
30
/// Wraps a future into a `MaybeDone`
31
-
///
32
-
/// # Examples
33
-
///
34
-
/// ```
35
-
/// # futures::executor::block_on(async {
36
-
/// use core::pin::pin;
37
-
///
38
-
/// use futures::future;
39
-
///
40
-
/// let future = future::maybe_done(async { 5 });
41
-
/// let mut future = pin!(future);
42
-
/// assert_eq!(future.as_mut().take_output(), None);
43
-
/// let () = future.as_mut().await;
44
-
/// assert_eq!(future.as_mut().take_output(), Some(5));
45
-
/// assert_eq!(future.as_mut().take_output(), None);
46
-
/// # });
47
-
/// ```
48
-
pub fn maybe_done<Fut: Future<LocalWaker>>(future: Fut) -> MaybeDone<Fut> {
31
+
pub fn maybe_done<Fut: futures_core::Future<LocalWaker>>(
32
+
future: Fut,
33
+
) -> MaybeDone<Fut> {
49
34
assert_future::<(), _>(MaybeDone::Future(future))
50
35
}
51
36
···
90
75
}
91
76
}
92
77
93
-
impl<Fut: Future<LocalWaker>> Future<LocalWaker> for MaybeDone<Fut> {
78
+
impl<Fut: Future<LocalWaker>> futures_core::Future<LocalWaker>
79
+
for MaybeDone<Fut>
80
+
{
94
81
type Output = ();
95
82
96
83
fn poll(
+1
futures/Cargo.toml
+1
futures/Cargo.toml
+6
-9
futures/src/lib.rs
+6
-9
futures/src/lib.rs
···
1
1
#![no_std]
2
2
3
-
pub use futures_combinators;
4
-
pub use futures_core;
5
-
use futures_core::ScopedFuture;
6
-
pub use futures_derive::async_scoped;
7
-
pub use futures_util;
3
+
use futures_compat::LocalWaker;
4
+
use futures_derive::async_function;
8
5
9
6
async fn evil() {}
10
7
11
-
#[async_scoped]
8
+
#[async_function]
12
9
fn inner(a: i32, b: &i32) -> i32 {
13
10
// evil().await;
14
11
1
15
12
}
16
13
17
-
#[async_scoped]
14
+
#[async_function]
18
15
fn test(a: i32, b: &i32) -> i32 {
19
-
futures_derive::block! { 1 + *b; 2 }.await
16
+
futures_derive::async_block! { let _ = 1 + *b; 2 }.await
20
17
}
21
18
22
-
fn test2<'a>(a: i32) {}
19
+
// fn test2<'a>(a: i32) {}