I'm creating a repeating task in Rust using the Tokio framework. The following code is based on a completed change request to add this feature to the tokio-timer crate.
When trying to compile, I get the error message:
error[E0281]: type mismatch: the type `fn() {my_cron_func}` implements the trait `std::ops::FnMut<()>`, but the trait `std::ops::FnMut<((),)>` is required (expected tuple, found ())
--> src/main.rs:19:36
|
19 | let background_tasks = wakeups.for_each(my_cron_func);
| ^^^^^^^^
error[E0281]: type mismatch: the type `fn() {my_cron_func}` implements the trait `std::ops::FnOnce<()>`, but the trait `std::ops::FnOnce<((),)>` is required (expected tuple, found ())
--> src/main.rs:19:36
|
19 | let background_tasks = wakeups.for_each(my_cron_func);
| ^^^^^^^^
error[E0281]: type mismatch: the type `fn() {my_cron_func}` implements the trait `std::ops::FnMut<()>`, but the trait `std::ops::FnMut<((),)>` is required (expected tuple, found ())
--> src/main.rs:20:10
|
20 | core.run(background_tasks).unwrap();
| ^^^
|
= note: required because of the requirements on the impl of `futures::Future` for `futures::stream::ForEach<tokio_timer::Interval, fn() {my_cron_func}, _>`
error[E0281]: type mismatch: the type `fn() {my_cron_func}` implements the trait `std::ops::FnOnce<()>`, but the trait `std::ops::FnOnce<((),)>` is required (expected tuple, found ())
--> src/main.rs:20:10
|
20 | core.run(background_tasks).unwrap();
| ^^^
|
= note: required because of the requirements on the impl of `futures::Future` for `futures::stream::ForEach<tokio_timer::Interval, fn() {my_cron_func}, _>`
The error states that the return signature for the my_cron_func function is incorrect. What do I need to change/add to get the signature correct so it compiles?
extern crate futures;
extern crate tokio_core;
extern crate tokio_timer;
use std::time::*;
use futures::*;
use tokio_core::reactor::Core;
use tokio_timer::*;
pub fn main() {
println!("The start");
let mut core = Core::new().unwrap();
let timer = Timer::default();
let duration = Duration::new(2, 0); // 2 seconds
let wakeups = timer.interval(duration);
// issues here
let background_tasks = wakeups.for_each(my_cron_func);
core.run(background_tasks).unwrap();
println!("The end???");
}
fn my_cron_func() {
println!("Repeating");
Ok(());
}
I'm not sure what part of the error message is causing you trouble, but...
type mismatch
You've provided the wrong type
the type
fn() {my_cron_func}
implements the traitstd::ops::FnMut<()>
When using my_cron_func
, which is a function that takes no arguments
but the trait
std::ops::FnMut<((),)>
is required
But a function that takes a single argument, the empty tuple, is required.
(expected tuple, found ())
And the compiler tries to narrow down the problem.
If you review the documentation for the library you are using, specifically tokio_timer::Interval
, you can see that it implements futures::Stream
with the associated type Item = ()
.
This changes the error message:
error[E0277]: the trait bound `(): futures::Future` is not satisfied
--> src/main.rs:19:36
|
19 | let background_tasks = wakeups.for_each(my_cron_func);
| ^^^^^^^^ the trait `futures::Future` is not implemented for `()`
|
= note: required because of the requirements on the impl of `futures::IntoFuture` for `()`
error[E0277]: the trait bound `(): futures::Future` is not satisfied
--> src/main.rs:20:10
|
20 | core.run(background_tasks).unwrap();
| ^^^ the trait `futures::Future` is not implemented for `()`
|
= note: required because of the requirements on the impl of `futures::IntoFuture` for `()`
= note: required because of the requirements on the impl of `futures::Future` for `futures::stream::ForEach<tokio_timer::Interval, fn(()) {my_cron_func}, ()>`
Reviewing the documentation for futures::Stream
, we can see that the closure passed to for_each
needs to return a value that can be turned into a future that will yield ()
:
fn for_each<F, U>(self, f: F) -> ForEach<Self, F, U>
where F: FnMut(Self::Item) -> U,
U: IntoFuture<Item=(), Error=Self::Error>,
Self: Sized
Your function attempts to return something, except that there's no return type and you've used a ;
to end the function:
fn my_cron_func(a: ()) {
println!("Repeating");
Ok(());
}
futures::future::ok
does the trick:
fn my_cron_func(_: ()) -> futures::future::FutureResult<(), tokio_timer::TimerError> {
println!("Repeating");
futures::future::ok(())
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With