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

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.

Related

Is it possible to update a struct from a thread?

In Rust is it possible to update a struct from a thread started in one of the structs member functions?
I have an example below and the error I am getting is that you can't use self as a variable name.
use std::time::Duration;
use glib::{clone, Continue, MainContext, PRIORITY_DEFAULT};
use adw::{Application, ApplicationWindow};
use adw::prelude::*;
use std::thread;
const APP_ID: &str = "org.struct_threads";
fn main() {
let app = Application::builder().application_id(APP_ID).build();
app.connect_activate(build_ui);
app.run();
}
pub fn build_ui(app: &Application) {
let window = ApplicationWindow::builder()
.application(app)
.build();
let window_clone = window.clone();
let astruct = aStruct { aString : String::new(), aBool : false };
astruct.update_string();
while true {
println!("aString = {}", astruct.aString);
};
}
struct aStruct {
aString : String,
aBool : bool
}
impl aStruct {
pub fn update_string(&mut self) {
let (sender, receiver) = MainContext::channel(PRIORITY_DEFAULT);
thread::spawn(move || {
loop {
//let thisString = "";
if self.aString == "Value two" {
sender.send("Value one").expect("Could not send through channel");
//thisString = "Value two";
}
else {
sender.send("Value two").expect("Could not send through channel");
//thisString = "Value one";
}
//self.aStinrg = thisString.to_string();
thread::sleep(Duration::from_secs(10));
};
});
receiver.attach(
None,
clone!(#weak self => #default-return Continue(false),
move |reciever_string| {
self.aString = reciever_string;
Continue(true)
}
),
);
}
}
Error:
error: proc macro panicked
--> src/main.rs:99:13
|
99 | / clone!(#weak self => #default-return Continue(false),
100 | | move |reciever_string| {
101 | | self.aString = reciever_string;
102 | | Continue(true)
103 | | }
104 | | ),
| |____________^
|
= help: message: Can't use `self` as variable name. Try storing it in a temporary variable or rename it using `as`.
If I clone self and pass a normal variable name into the receiver I get an error stating that the struct does not implement Downgrade which doesn't seem to be implementable for booleans.
I get the same Downgrade error if I try and move this block into a non member function of the struct and call it separately.
Downgrade error:
error[E0277]: the trait bound `aStruct: Downgrade` is not satisfied
--> src/main.rs:99:13
|
99 | / clone!(#weak self_clone => #default-return Continue(false),
100 | | move |reciever_string| {
101 | | self.aString = reciever_string.to_string();
102 | | Continue(true)
103 | | }
104 | | ),
| |____________^ the trait `Downgrade` is not implemented for `aStruct`
|
= help: the following other types implement trait `Downgrade`:
&T
ATContext
AboutDialog
AboutWindow
Accessible
Action
ActionBar
ActionGroup
and 493 others
= note: required for `&aStruct` to implement `Downgrade`
= note: this error originates in the macro `clone` (in Nightly builds, run with -Z macro-backtrace for more info)
Finally if I just try and update the struct from within the thread using either self or a copy I get an error stating that the value does not live long enough. Is there way to update a struct from a thread?

Rust declare first assign later pattern

I have a bi-directional grpc stream that acts as bridge to a kafka cluster. When the stream is first initialised, I was to create the kafka consumer and start using it.
To do so, I thought of initialising an empty consumer, waiting for the first input, then assigning a created consumer to an empty one. I tried to do so by following the pattern here.
https://doc.rust-lang.org/rust-by-example/variable_bindings/declare.html
Rust is throwing a possibly-unitialized variable error, is this because it is being initialised in an asynchronous stream?
use std::pin::Pin;
use futures::{Stream, StreamExt};
use kafka::consumer::{Consumer, FetchOffset, GroupOffsetStorage};
use tonic::transport::Server;
use tonic::{Request, Response, Status};
use bridge::kafka_stream_server::{KafkaStream, KafkaStreamServer};
use bridge::{KafkaResponse, PublishRequest};
pub mod bridge {
tonic::include_proto!("bridge"); // The string specified here must match the proto package name
}
#[derive(Default)]
pub struct KafkaStreamService {}
pub fn create_kafka_consumer(topic: String) -> Consumer {
Consumer::from_hosts(vec!["localhost:9092".to_owned()])
.with_topic(topic.to_owned())
.with_fallback_offset(FetchOffset::Latest)
.with_group("".to_owned())
.with_offset_storage(GroupOffsetStorage::Kafka)
.create()
.unwrap()
}
#[tonic::async_trait]
impl KafkaStream for KafkaStreamService {
type SubscribeStream =
Pin<Box<dyn Stream<Item = Result<KafkaResponse, Status>> + Send + Sync + 'static>>;
async fn subscribe(
&self,
request: Request<tonic::Streaming<PublishRequest>>,
) -> Result<Response<Self::SubscribeStream>, Status> {
println!("Initiated stream!");
let mut stream = request.into_inner();
let mut consumer_created_flag: bool = false;
let consumer: Consumer; //declared here
let output = async_stream::try_stream! {
while let Some(publication) = stream.next().await {
let message = publication?;
let topic = message.topic.clone();
if consumer_created_flag == false {
consumer = create_kafka_consumer(topic); //error occurs here
consumer_created_flag = true;
}
let reply = bridge::KafkaResponse {
content: format!("Hello {}!", "world"),
};
yield reply.clone();
}
};
Ok(Response::new(Box::pin(output) as Self::SubscribeStream))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse().unwrap();
println!("KafkaService listening on: {}", addr);
let svc = KafkaStreamServer::new(KafkaStreamService::default());
Server::builder().add_service(svc).serve(addr).await?;
Ok(())
}
EDIT: verbose error as requested:
error[E0381]: use of possibly-uninitialized variable: `consumer`
--> src/server.rs:42:22
|
42 | let output = async_stream::try_stream! {
| ______________________^
43 | | while let Some(publication) = stream.next().await {
44 | | let message = publication?;
45 | | let topic = message.topic.clone();
46 | | if consumer_created_flag == false {
47 | | consumer = create_kafka_consumer(topic);
| | -------- use occurs due to use in generator
... |
54 | | }
55 | | };
| |_________^ use of possibly-uninitialized `consumer`
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
The declare first pattern only works with basic control flow (if, match, {}, etc). It falls apart when referenced or moved into another object, like an async block or a closure:
fn main() {
let val: i32;
let func = move || {
val = 5;
};
}
error[E0594]: cannot assign to `val`, as it is not declared as mutable
--> src/main.rs:4:9
|
2 | let val: i32;
| --- help: consider changing this to be mutable: `mut val`
3 | let func = move || {
4 | val = 5;
| ^^^^^^^ cannot assign
error[E0381]: use of possibly-uninitialized variable: `val`
--> src/main.rs:3:16
|
3 | let func = move || {
| ^^^^^^^ use of possibly-uninitialized `val`
4 | val = 5;
| --- use occurs due to use in closure
A potential fix is to move its declaration into the try_stream! macro:
let output = async_stream::try_stream! {
let mut consumer_created_flag: bool = false;
let consumer: Consumer;
while let Some(publication) = stream.next().await {
let message = publication?;
let topic = message.topic.clone();
if consumer_created_flag == false {
consumer = create_kafka_consumer(topic);
consumer_created_flag = true;
}
let reply = KafkaResponse {
content: format!("Hello {}!", "world"),
};
yield reply.clone();
}
};
However, this causes a new error because you're potentially assigning to it twice (the compiler doesn't know that consumer_created_flag is guarding it):
error[E0384]: cannot assign twice to immutable variable `consumer`
--> src\lib.rs:1348:21
|
44 | let consumer: Consumer; //declared here
| -------- help: make this binding mutable: `mut consumer`
...
49 | consumer = create_kafka_consumer(topic); //error occurs here
| ^^^^^^^^ cannot assign twice to immutable variable
Fortunately a quick fix is to simply make consumer mutable. And then the only thing the compiler complains about is that it is unused, but I figure there's a reason you've put it there.

Why does a match statement without a trailing semicolon cause an error? [duplicate]

I'm rewriting a simple TCP based server to experiment with Rust. It should retrieve input of an client and then match that input to run a function:
use std::io::BufRead;
use std::io::BufReader;
use std::io::BufWriter;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::thread;
fn handle_connection(stream: TcpStream) {
let stream_clone = stream.try_clone().unwrap();
let mut reader = BufReader::new(stream);
let mut writer = BufWriter::new(stream_clone);
loop {
let mut s = String::new();
reader.read_line(&mut s).unwrap();
match s.as_str() {
//"test" => writer.write(s.as_bytes()).unwrap();
"test" => writer.write(b"test successfull").unwrap(),
_ => writer.write(b"Command not recognized...").unwrap(),
}
writer.flush().unwrap();
}
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:8888").unwrap();
for stream in listener.incoming() {
thread::spawn(move || {
handle_connection(stream.unwrap());
});
}
}
And the error:
error[E0308]: mismatched types
--> src/main.rs:16:9
|
16 | / match s.as_str() {
17 | | //"test" => writer.write(s.as_bytes()).unwrap();
18 | | "test" => writer.write(b"test successfull").unwrap(),
19 | | _ => writer.write(b"Command not recognized...").unwrap(),
20 | | }
| |_________^ expected (), found usize
|
= note: expected type `()`
found type `usize`
My main problem now is to check the retrieved bytes if they belong to an match and I'm not quite sure how to achieve that.
I couldn't find a fix for this online, rustc --explain didn't help me either
Add a semicolon after your match expression.
The type of all of the match arms is usize, so the resulting type of the match is also a usize. Your code is effectively
fn main() {
{
42
}
println!("Hi");
}
error[E0308]: mismatched types
--> src/main.rs:3:9
|
3 | 42
| ^^ expected `()`, found integer
See also:
Why don't we add a semicolon (;) at the end of if/else?
Are semicolons optional in Rust?

What does "expected type `()`" mean on a match expression?

I'm rewriting a simple TCP based server to experiment with Rust. It should retrieve input of an client and then match that input to run a function:
use std::io::BufRead;
use std::io::BufReader;
use std::io::BufWriter;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::thread;
fn handle_connection(stream: TcpStream) {
let stream_clone = stream.try_clone().unwrap();
let mut reader = BufReader::new(stream);
let mut writer = BufWriter::new(stream_clone);
loop {
let mut s = String::new();
reader.read_line(&mut s).unwrap();
match s.as_str() {
//"test" => writer.write(s.as_bytes()).unwrap();
"test" => writer.write(b"test successfull").unwrap(),
_ => writer.write(b"Command not recognized...").unwrap(),
}
writer.flush().unwrap();
}
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:8888").unwrap();
for stream in listener.incoming() {
thread::spawn(move || {
handle_connection(stream.unwrap());
});
}
}
And the error:
error[E0308]: mismatched types
--> src/main.rs:16:9
|
16 | / match s.as_str() {
17 | | //"test" => writer.write(s.as_bytes()).unwrap();
18 | | "test" => writer.write(b"test successfull").unwrap(),
19 | | _ => writer.write(b"Command not recognized...").unwrap(),
20 | | }
| |_________^ expected (), found usize
|
= note: expected type `()`
found type `usize`
My main problem now is to check the retrieved bytes if they belong to an match and I'm not quite sure how to achieve that.
I couldn't find a fix for this online, rustc --explain didn't help me either
Add a semicolon after your match expression.
The type of all of the match arms is usize, so the resulting type of the match is also a usize. Your code is effectively
fn main() {
{
42
}
println!("Hi");
}
error[E0308]: mismatched types
--> src/main.rs:3:9
|
3 | 42
| ^^ expected `()`, found integer
See also:
Why don't we add a semicolon (;) at the end of if/else?
Are semicolons optional in Rust?

How to reduce lifetime conflicts?

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

Resources