How to reduce lifetime conflicts? - rust

I'm fear about lifetime question. I searched and got so many relative results. I feel so different between of them, and I think it is difficult to get the spirit from them. so I decide to ask.
The error occurred when invoking dao's method inside a Hyper service's call, and I can't fix it!
extern crate futures;
extern crate hyper;
use futures::future::Future;
use futures::Stream;
use hyper::server::{Http, Request, Response, Service};
use hyper::StatusCode;
use std::net::SocketAddr;
trait Dao {
fn input_data(&self, data: &str) -> bool;
}
struct MysqlDao;
impl Dao for MysqlDao {
fn input_data(&self, data: &str) -> bool {
unimplemented!()
}
}
struct HelloWorld<'a> {
dao: &'a Dao,
}
impl<'a> Service for HelloWorld<'a> {
type Request = Request;
type Response = Response;
type Error = hyper::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn call(&self, req: Request) -> Self::Future {
Box::new(req.body().concat2().map(|b| {
let rtn = self.dao.input_data(std::str::from_utf8(b.as_ref()).unwrap());
let rtn = true; // line 35 this is ok
match rtn {
true => {
return Response::new()
.with_status(StatusCode::Ok)
.with_body(String::from("ok"));
}
false => {
return Response::new()
.with_status(StatusCode::UnprocessableEntity)
.with_body(String::from("error"));
}
}
}))
}
}
fn main() {
let addr = "127.0.0.1:3000".parse().unwrap();
static DAO: MysqlDao = MysqlDao;
web_startup(&addr, &DAO);
}
fn web_startup<T: Dao>(addr: &SocketAddr, dao: &'static T) {
let server = Http::new()
.bind(addr, move || Ok(HelloWorld { dao }))
.unwrap();
server.run().unwrap();
}
playground
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:33:9
|
33 | / Box::new(req.body().concat2().map(|b| {
34 | | let rtn = self.dao.input_data(std::str::from_utf8(b.as_ref()).unwrap());
35 | | let rtn = true; // line 35 this is ok
36 | | match rtn {
... |
47 | | }
48 | | }))
| |___________^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 26:1...
--> src/main.rs:26:1
|
26 | / impl<'a> Service for HelloWorld<'a> {
27 | | type Request = Request;
28 | | type Response = Response;
29 | | type Error = hyper::Error;
... |
49 | | }
50 | | }
| |_^
note: ...so that the type `futures::Map<futures::stream::Concat2<hyper::Body>, [closure#src/main.rs:33:43: 48:10 self:&&HelloWorld<'a>]>` will meet its required lifetime bounds
--> src/main.rs:33:9
|
33 | / Box::new(req.body().concat2().map(|b| {
34 | | let rtn = self.dao.input_data(std::str::from_utf8(b.as_ref()).unwrap());
35 | | let rtn = true; // line 35 this is ok
36 | | match rtn {
... |
47 | | }
48 | | }))
| |___________^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that expression is assignable (expected std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>, found std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response>>)
--> src/main.rs:33:9
|
33 | / Box::new(req.body().concat2().map(|b| {
34 | | let rtn = self.dao.input_data(std::str::from_utf8(b.as_ref()).unwrap());
35 | | let rtn = true; // line 35 this is ok
36 | | match rtn {
... |
47 | | }
48 | | }))
| |___________^
The problem line is 34. When I replace line 34 with line 35, it works.

There's a couple of things going on with lifetimes in this code, and the error message is not that great.
The first thing is that your call function returns a trait object; that is, Box<T> where T is a trait instead of a concrete type. The default lifetime for a trait object is 'static, so Box<Future> is equivalent to Box<Future + 'static>. That explains where this line of the message comes from:
note: ...so that expression is assignable (expected std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>, found std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response>>)
In this case, you don't need your returned Future to have the 'static lifetime. Instead, you want it to have the same lifetime as self.dao, so change your type alias as follows:
type Future = Box<'a + Future<Item = Self::Response, Error = Self::Error>>;
The second thing is what variables your closure captures. Your closure refers to self, so it needs to save away that reference. This means the closure can't live past the end of the method - but you've already specified it will live as long as 'a; that is, it will live at least as long as self.dao.
Note that self in this method does not have the lifetime 'a. The instance of HelloWorld might have a shorter lifetime than the dao it has a reference to.
To fix this half of the problem, you need to allow the closure to capture only self.dao without capturing self. So you have to add
let dao = self.dao;
before the closure, and then refer to dao instead of self.dao inside the closure, so that it won't capture self. You also need to make the closure a move closure, otherwise it ends up capturing a reference to the reference, which still ties the lifetime to the scope of the function.
User red75prime, who originally posted this suggestion in a comment, made a playground with these changes. Lines 30, 33, and 34 are the important ones.

I found a way, but I think it's ugly.
Remove dao property from HelloWorld; add Sync to trait Dao; move out DAO to upper scope; invoke DAO directly from fn call.
Code : playground

Related

use an object inside a closure which is passed to a method of that object

i have a struct Screen with its implementation
pub struct Screen {
stdin: Stdin,
// types are irrelevant
stdout: MouseStdout,
}
impl Screen {
// ...
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
&self,
mut handler: F,
) {
let stdin = stdin();
for e in stdin.events() {
let e = e.unwrap();
match e {
Event::Key(Key::Ctrl('c')) => break,
_ => {
handler(&e);
},
}
}
}
}
and usage (which is wrong and know it)
let mut screen = Screen::new();
screen.init_screen();
screen.handle_keys_loop(|event| {
match event {
Event::Key(Key::Char('a')) => {
screen.println("hello there",15, 1, true);
},
_ => {}
}
});
screen.end_screen();
the error is
error[E0502]: cannot borrow `screen` as mutable because it is also borrowed as immutable
--> src/bin/terminal.rs:74:29
|
74 | screen.handle_keys_loop(|event| {
| - ---------------- ^^^^^^^ mutable borrow occurs here
| | |
| _____| immutable borrow later used by call
| |
75 | | match event {
76 | | Event::Key(Key::Char('a')) => {
77 | | println!("{} {} {} {}", "do something with a", 15, 1, true);
78 | | // tried to borrow as mutable
79 | | screen.println("hello there",15, 1, true);
| | ------ second borrow occurs due to use of `screen` in closure
... |
82 | | }
83 | | });
| |______- immutable borrow occurs here
and if i make self mut inside handle_keys_loop to get rid of cannot borrow screen as mutable because it is also borrowed as immutable
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
+ &mut self,
- &self
....
i get this error
error[E0499]: cannot borrow `screen` as mutable more than once at a time
--> src/bin/terminal.rs:74:29
|
74 | screen.handle_keys_loop(|event| {
| - ---------------- ^^^^^^^ second mutable borrow occurs here
| | |
| _____| first borrow later used by call
| |
75 | | match event {
76 | | Event::Key(Key::Char('a')) => {
77 | | screen.println("hello there",15, 1, true);
| | ------ second borrow occurs due to use of `screen` in closure
... |
80 | | }
81 | | });
| |______- first mutable borrow occurs here
what im trying to do: use the method handle_keys_loop of screen and pass screen inside the closure, which is passed to handle_keys_loop. basically, to use screen inside of screen.
how do i achieve that ?
some people told me to use RefCell, but that didnt work out very well, i got BorrowError.
i will use any workaround to just use screen inside the closure which is passed to screen's method.
thanks in advance.
One pattern I use to handle such a situation is to pass self: &mut Self back into the closure from handle and use that inside the closure. A simplified version of your code:
struct Screen {}
struct Event {}
impl Screen {
fn handle<F: FnMut(&mut Screen, Event)>(&mut self, mut handler: F) {
handler(self, Event {})
}
fn print(&mut self) {}
}
fn main() {
let mut screen = Screen {};
screen.handle(|screen, _event| screen.print());
screen.handle(|screen, _event| screen.print());
}
You can't do what you're trying to do because it violates Rust's rule that you can't mutate a value while something else has access to it.
However, your handle_keys_loop method doesn't even use self which means the &self parameter is redundant. There's no reason to give a function an argument it's not going to use (except when implementing a trait that requires it).
Just remove the argument:
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
mut handler: F,
) {
And call it as Screen::handle_keys_loop(|event| { ... }).
Alternatively, make it a free function, external to Screen entirely, since it doesn't depend on Screen in any way.

Why does one of these two very similar async Rust functions trigger thread safety errors?

I'm trying something as a learn-Rust project, where I have a library that consumes some REST APIs through a HTTP request trait that I planned to fill in separately for native and webassembly usage, so that I could have bindings for this library in different environments.
My problem arises in the WASM portion, where I'm trying to adapt the fetch example here:
pub async fn run(url: String, authz: String) -> Result<serde_json::Value, JsValue> {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::Cors);
let request = Request::new_with_str_and_init(&url, &opts)?;
request.headers().set("Authorization", &authz)?;
let window = web_sys::window().unwrap();
let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?;
assert!(resp_value.is_instance_of::<Response>());
let resp: Response = resp_value.dyn_into().unwrap();
let json = JsFuture::from(resp.json()?).await?;
let parsed: serde_json::Value = json.into_serde().unwrap();
Ok(parsed)
}
I made some light adaptations to suit my purpose here, but it works fine. What doesn't work is my attempt to shoehorn this into the trait interface. The return type is an anyhow::Result, and I unwrap() a bunch of stuff I shouldn't here to temporarily avoid issues with the error type compatibility:
#[async_trait]
impl FetchRequest for WasmFetchRequest {
async fn get(&mut self) -> Result<serde_json::Value> {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::Cors);
let request = Request::new_with_str_and_init(&self.path, &opts).unwrap();
request.headers().set("Authorization", &self.authz);
let window = web_sys::window().unwrap();
let resp_value = JsFuture::from(window.fetch_with_request(&request)).await.unwrap();
assert!(resp_value.is_instance_of::<Response>());
let resp: Response = resp_value.dyn_into().unwrap();
let json = JsFuture::from(resp.json().unwrap()).await.unwrap();
let parsed: serde_json::Value = resp.into_serde().unwrap();
Ok(parsed)
/*
// hoped this might work too, same errors
Ok(run(
self.path.to_string(),
self.authz.to_string()
).await.map_err(|err| err.into())?);
*/
}
}
The build is unhappy:
error: future cannot be sent between threads safely
--> src/lib.rs:66:58
|
66 | async fn get(&mut self) -> Result<serde_json::Value> {
| __________________________________________________________^
67 | | /*
68 | | Ok(run(
69 | | self.path.to_string(),
... |
91 | | Ok(parsed)
92 | | }
| |_____^ future created by async block is not `Send`
|
= help: within `impl Future`, the trait `Send` is not implemented for `Rc<RefCell<wasm_bindgen_futures::Inner>>`
note: future is not `Send` as it awaits another future which is not `Send`
--> src/lib.rs:83:26
|
83 | let resp_value = JsFuture::from(window.fetch_with_request(&request)).await.unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `JsFuture`, which is not `Send`
= note: required for the cast to the object type `dyn Future<Output = Result<Value, rescale_core::Error>> + Send`
error: future cannot be sent between threads safely
--> src/lib.rs:66:58
|
66 | async fn get(&mut self) -> Result<serde_json::Value> {
| __________________________________________________________^
67 | | /*
68 | | Ok(run(
69 | | self.path.to_string(),
... |
91 | | Ok(parsed)
92 | | }
| |_____^ future created by async block is not `Send`
|
= help: within `impl Future`, the trait `Send` is not implemented for `*mut u8`
note: future is not `Send` as this value is used across an await
--> src/lib.rs:88:20
|
83 | let resp_value = JsFuture::from(window.fetch_with_request(&request)).await.unwrap();
| ---------- has type `wasm_bindgen::JsValue` which is not `Send`
...
88 | let json = JsFuture::from(resp.json().unwrap()).await.unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `resp_value` maybe used later
...
92 | }
| - `resp_value` is later dropped here
= note: required for the cast to the object type `dyn Future<Output = Result<Value, rescale_core::Error>> + Send`
error: future cannot be sent between threads safely
--> src/lib.rs:66:58
|
66 | async fn get(&mut self) -> Result<serde_json::Value> {
| __________________________________________________________^
67 | | /*
68 | | Ok(run(
69 | | self.path.to_string(),
... |
91 | | Ok(parsed)
92 | | }
| |_____^ future created by async block is not `Send`
|
= help: within `Request`, the trait `Sync` is not implemented for `*mut u8`
note: future is not `Send` as this value is used across an await
--> src/lib.rs:83:26
|
83 | let resp_value = JsFuture::from(window.fetch_with_request(&request)).await.unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ first, await occurs here, with `&request` maybe used later...
note: `&request` is later dropped here
--> src/lib.rs:83:92
|
83 | let resp_value = JsFuture::from(window.fetch_with_request(&request)).await.unwrap();
| -------- ^
| |
| has type `&Request` which is not `Send`
help: consider moving this into a `let` binding to create a shorter lived borrow
--> src/lib.rs:83:41
|
83 | let resp_value = JsFuture::from(window.fetch_with_request(&request)).await.unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required for the cast to the object type `dyn Future<Output = Result<Value, rescale_core::Error>> + Send`
What is the pertinent difference here that causes these errors? I think it must be something with &mut self or else the return type, but I'm out of my depth.
Probably not relevant, but the native counterpart fits into the interface happily enough:
#[async_trait]
impl FetchRequest for NativeFetchRequest {
async fn get(&mut self) -> Result<serde_json::Value> {
let client = reqwest::Client::new();
let mut req = client.get(&self.path);
req = req.header("Authorization", self.authz.as_str());
let res = req.send().await?;
res.error_for_status()?
.json::<serde_json::Value>().await
.map_err(|err| err.into())
}
}
According to async_trait documentation, futures returned by async trait methods must by default be Send:
Async fns get transformed into methods that return Pin<Box<dyn Future + Send + 'async>> and delegate to a private async freestanding function.
Your async fn produced a non-Send future. So the difference between your original code and the one that uses async_trait was that the original code didn't require a Send future, it was okay with non-Send ones, whereas async_trait by default expects Send futures.
To fix the issue, you need to tell async_trait not to require Send using #[async_trait(?Send)] on the trait and the impl block. In other words, replace #[async_trait] with #[async_trait(?Send)] in both the trait declaration and the implementation, and your code should compile. (Playground.)

Why does i got lifetime error in rust closure

I'm testing some rust wasm features, and have some problem with closures.
I'm implemented this function, which setup callback on button click event.
pub fn setup_click(&mut self) {
let mut clicks = 0;
let ws_cloned = self.websocket.clone();
let num_clicks_cloned = self.num_clicks.clone();
let notifications = Rc::new(RefCell::new(Notificator::new(
NotificationConfig::new_default(),
)));
let cb = move |_: Event| {
clicks += 1;
num_clicks_cloned
.borrow_mut()
.set_inner_html(clicks.to_string());
let mut map: Map<String, Value> = serde_json::Map::new();
map.insert("key".to_string(), Value::String(clicks.to_string()));
if let Ok(ws) = ws_cloned.clone().try_borrow_mut() {
ws.send_rpc(
String::from("click"),
Params::Map(map),
Box::new(|payload: String| {
notifications.clone().borrow_mut().display(
payload,
"Click success".to_string(),
"success".to_string(),
)
}),
);
}
};
self.click_button.add_event_listener("click", cb);
}
where third param of the ws.send rpc is
pub type RPCHandler = Box<dyn Fn(String) + 'static>;
and add_event_listener has this sugnature
pub fn add_event_listener<T>(&mut self, event_name: &str, handler: T)
where
T: 'static + FnMut(web_sys::Event),
{
let cb = Closure::wrap(Box::new(handler) as Box<dyn FnMut(_)>);
if let Some(el) = self.el.take() {
let el_et: EventTarget = el.into();
el_et
.add_event_listener_with_callback(event_name, cb.as_ref().unchecked_ref())
.unwrap();
cb.forget();
if let Ok(el) = el_et.dyn_into::<web_sys::Element>() {
self.el = Some(el);
}
}
}
When i try to compile the code i got life time error
--> src/test_click_btn.rs:46:21
|
35 | let cb = move |_: Event| {
| --------------- lifetime `'1` represents this closure's body
...
46 | / Box::new(|payload: String| {
47 | | notifications.clone().borrow_mut().display(
48 | | payload,
49 | | "Click success".to_string(),
50 | | "success".to_string(),
51 | | )
52 | | }),
| |______________________^ cast requires that `'1` must outlive `'static`
|
= note: closure implements `FnMut`, so references to captured variables can't escape the closure```
I see that notifications not live long enough, but can't understand how to fix this error)
There's no guarantee in this code that the closure passed to send_rpc will last no longer than the event callback closure. Therefore, it needs to be made a move closure too, so that it can live independently rather than borrowing from the event handler closure.
Conveniently, you already have notifications wrapped in Rc, which is just what you need, but you've performed the clone in the wrong place. This line
notifications.clone().borrow_mut().display(
performs a clone and dereferences it immediately, so it's redundant. Instead, you need to clone it before creating the closure so that the closure (now move) can own it:
let notifications = notifications.clone(); // create a clone that will be moved into the closure
ws.send_rpc(
String::from("click"),
Params::Map(map),
Box::new(move |payload: String| { // now a move closure
notifications.borrow_mut().display( // no clone here
...

Error on Future generator closure: Captured variable cannot escape `FnMut` closure body

I want to create a simple websocket server. I want to process the incoming messages and send a response, but I get an error:
error: captured variable cannot escape `FnMut` closure body
--> src\main.rs:32:27
|
32 | incoming.for_each(|m| async {
| _________________________-_^
| | |
| | inferred to be a `FnMut` closure
33 | | match m {
34 | | // Error here...
35 | | Ok(message) => do_something(message, db, &mut outgoing).await,
36 | | Err(e) => panic!(e)
37 | | }
38 | | }).await;
| |_____^ returns a reference to a captured variable which escapes the closure body
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
This gives a few hits on Stack Overflow but I don't see anywhere in my code where a variable is escaping. The async block won't run concurrently, so I don't see any problem. Furthermore, I feel like I am doing something very simple: I get a type which allows me to send data back to the client, but when using a reference to it in the async block, it gives a compile error. The error only occurs when I use the outgoing or db variable in the async code.
This is my code (error is in the handle_connection function):
main.rs
use tokio::net::{TcpListener, TcpStream};
use std::net::SocketAddr;
use std::sync::Arc;
use futures::{StreamExt, SinkExt};
use tungstenite::Message;
use tokio_tungstenite::WebSocketStream;
struct DatabaseConnection;
#[tokio::main]
async fn main() -> Result<(), ()> {
listen("127.0.0.1:3012", Arc::new(DatabaseConnection)).await
}
async fn listen(address: &str, db: Arc<DatabaseConnection>) -> Result<(), ()> {
let try_socket = TcpListener::bind(address).await;
let mut listener = try_socket.expect("Failed to bind on address");
while let Ok((stream, addr)) = listener.accept().await {
tokio::spawn(handle_connection(stream, addr, db.clone()));
}
Ok(())
}
async fn handle_connection(raw_stream: TcpStream, addr: SocketAddr, db: Arc<DatabaseConnection>) {
let db = &*db;
let ws_stream = tokio_tungstenite::accept_async(raw_stream).await.unwrap();
let (mut outgoing, incoming) = ws_stream.split();
// Adding 'move' does also not work
incoming.for_each(|m| async {
match m {
// Error here...
Ok(message) => do_something(message, db, &mut outgoing).await,
Err(e) => panic!(e)
}
}).await;
}
async fn do_something(message: Message, db: &DatabaseConnection, outgoing: &mut futures_util::stream::SplitSink<WebSocketStream<TcpStream>, Message>) {
// Do something...
// Send some message
let _ = outgoing.send(Message::Text("yay".to_string())).await;
}
Cargo.toml
[dependencies]
futures = "0.3.*"
futures-channel = "0.3.*"
futures-util = "0.3.*"
tokio = { version = "0.2.*", features = [ "full" ] }
tokio-tungstenite = "0.10.*"
tungstenite = "0.10.*"
When using async move, I get the following error:
code
incoming.for_each(|m| async move {
let x = &mut outgoing;
let b = db;
}).await;
error
error[E0507]: cannot move out of `outgoing`, a captured variable in an `FnMut` closure
--> src\main.rs:33:38
|
31 | let (mut outgoing, incoming) = ws_stream.split();
| ------------ captured outer variable
32 |
33 | incoming.for_each(|m| async move {
| ______________________________________^
34 | | let x = &mut outgoing;
| | --------
| | |
| | move occurs because `outgoing` has type `futures_util::stream::stream::split::SplitSink<tokio_tungstenite::WebSocketStream<tokio::net::tcp::stream::TcpStream>, tungstenite::protocol::message::Message>`, which does not implement the `Copy` trait
| | move occurs due to use in generator
35 | | let b = db;
36 | | }).await;
| |_____^ move out of `outgoing` occurs here
FnMut is an anonymous struct, since FnMutcaptured the &mut outgoing, it becomes a field inside of this anonymous struct and this field will be used on each call of FnMut , it can be called multiple times. If you lose it somehow (by returning or moving into another scope etc...) your program will not able to use that field for further calls, due to safety Rust Compiler doesn't let you do this(for your both case).
In your case instead of capturing the &mut outgoing we can use it as argument for each call, with this we'll keep the ownership of outgoing. You can do this by using fold from futures-rs:
incoming
.fold(outgoing, |mut outgoing, m| async move {
match m {
// Error here...
Ok(message) => do_something(message, db, &mut outgoing).await,
Err(e) => panic!(e),
}
outgoing
})
.await;
This may seem a bit tricky but it does the job, we are using constant accumulator(outgoing) which will be used as an argument for our FnMut.
Playground (Thanks #Solomon Ucko for creating reproducible example)
See also :
How to return the captured variable from `FnMut` closure, which is a captor at the same time
How can I move a captured variable into a closure within a closure?

"Closure takes 0 arguments" on a closure that takes an argument

I am attempting to pass a closure to a function after a condition:
extern crate futures;
extern crate tokio_core;
use futures::prelude::*;
use futures::future;
use futures::unsync::*;
use tokio_core::reactor::*;
fn main() {
let mut core = Core::new().unwrap();
let h2 = core.handle();
let fun = |should: Result<bool, ()>| {
if should.unwrap_or(true) {
// do something
}
future::ok(())
};
let (tx, rx) = oneshot::channel::<bool>();
let dummy = true;
if dummy {
h2.spawn(rx.then(fun));
} else {
h2.spawn(future::ok(true).then(fun));
}
core.run(future::ok::<(), ()>(())).unwrap();
}
Here is the code in the playground, but it is getting a different error from the error baffling me. My error looks like:
error[E0593]: closure takes 0 arguments but 1 argument is required
--> src/client/forger.rs:123:25
|
57 | let fun = |should: Result<bool, ()>| {
| ___________________-
58 | | if !should.unwrap_or(false) {
59 | | return Box::new(future::ok::<(), ()>(()));
60 | | }
... |
117 | | Box::new(future::ok(()))
118 | | };
| |_________- takes 0 arguments
...
123 | h2.spawn(rx.then(fun));
| ^^^^ expected closure that takes 1 argument
Why does Rust say the function fun takes 0 arguments when it appears to quote it as taking one?
My Rust version is 1.22.1.
Turns out that my Rust version was 1.22.1, but the latest version is 1.23.0. This explains why the playground was returning a more accurate error: expected signature of fn(std::result::Result<bool, futures::Canceled>) -> _... which was the problem exactly.

Resources