Can't compile since opentelemetry and opentelemetry-jaeger update - rust

I have this function that is working perfectly fine with opentelemetry = { version = "0.17", features = ["tokio"] } and opentelemetry-jaeger = { version = "0.16", features = ["rt-tokio"] }
pub fn get_subscriber(name: String, env_filter: String) -> impl Subscriber + Sync + Send {
// Building the jaeger layer, if needed
let telemetry = if std::env::var("JAEGER_ENABLED").is_ok() {
let tracer = opentelemetry_jaeger::new_pipeline()
.with_service_name(&name)
.install_batch(opentelemetry::runtime::Tokio)
.unwrap();
Some(tracing_opentelemetry::layer().with_tracer(tracer))
} else {
None
};
let env_filter =
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(env_filter));
let formatting_layer = BunyanFormattingLayer::new(name, std::io::stdout);
Registry::default()
.with(env_filter)
.with(JsonStorageLayer)
.with(formatting_layer)
.with(sentry_tracing::layer())
.with(telemetry)
}
Everything works fine like this, and I can find my trace in Jaeger when it is enabled.
Since I update to opentelemetry = { version = "0.18", features = ["rt-tokio"] } and
opentelemetry-jaeger = { version = "0.17", features = ["rt-tokio"] } It won't compile anymore
Compiling rss-common v0.1.0 (/home/eric/dev/rss-aggregator/rss-common)
error[E0277]: the trait bound `opentelemetry::sdk::trace::Tracer: opentelemetry::trace::tracer::Tracer` is not satisfied
--> rss-common/src/observability.rs:14:57
|
14 | Some(tracing_opentelemetry::layer().with_tracer(tracer))
| ----------- ^^^^^^ the trait `opentelemetry::trace::tracer::Tracer` is not implemented for `opentelemetry::sdk::trace::Tracer`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `opentelemetry::trace::tracer::Tracer`:
opentelemetry::global::trace::BoxedTracer
opentelemetry::sdk::trace::tracer::Tracer
opentelemetry::trace::noop::NoopTracer
note: required by a bound in `OpenTelemetryLayer::<S, T>::with_tracer`
--> /home/eric/.cargo/registry/src/github.com-1ecc6299db9ec823/tracing-opentelemetry-0.17.4/src/layer.rs:464:17
|
464 | Tracer: otel::Tracer + PreSampledTracer + 'static,
| ^^^^^^^^^^^^ required by this bound in `OpenTelemetryLayer::<S, T>::with_tracer`
error[E0277]: the trait bound `opentelemetry::sdk::trace::Tracer: PreSampledTracer` is not satisfied
--> rss-common/src/observability.rs:14:57
|
14 | Some(tracing_opentelemetry::layer().with_tracer(tracer))
| ----------- ^^^^^^ the trait `PreSampledTracer` is not implemented for `opentelemetry::sdk::trace::Tracer`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `PreSampledTracer`:
opentelemetry::sdk::trace::tracer::Tracer
opentelemetry::trace::noop::NoopTracer
note: required by a bound in `OpenTelemetryLayer::<S, T>::with_tracer`
--> /home/eric/.cargo/registry/src/github.com-1ecc6299db9ec823/tracing-opentelemetry-0.17.4/src/layer.rs:464:32
|
464 | Tracer: otel::Tracer + PreSampledTracer + 'static,
| ^^^^^^^^^^^^^^^^ required by this bound in `OpenTelemetryLayer::<S, T>::with_tracer`
error[E0277]: the trait bound `opentelemetry::sdk::trace::Tracer: opentelemetry::trace::tracer::Tracer` is not satisfied
--> rss-common/src/observability.rs:28:15
|
28 | .with(telemetry)
| ---- ^^^^^^^^^ the trait `opentelemetry::trace::tracer::Tracer` is not implemented for `opentelemetry::sdk::trace::Tracer`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `opentelemetry::trace::tracer::Tracer`:
opentelemetry::global::trace::BoxedTracer
opentelemetry::sdk::trace::tracer::Tracer
opentelemetry::trace::noop::NoopTracer
= note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>` for `OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>`
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>` for `Option<OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>>`
note: required by a bound in `with`
--> /home/eric/.cargo/registry/src/github.com-1ecc6299db9ec823/tracing-subscriber-0.3.15/src/layer/mod.rs:1440:12
|
1440 | L: Layer<Self>,
| ^^^^^^^^^^^ required by this bound in `with`
error[E0277]: the trait bound `opentelemetry::sdk::trace::Tracer: PreSampledTracer` is not satisfied
--> rss-common/src/observability.rs:28:15
|
28 | .with(telemetry)
| ---- ^^^^^^^^^ the trait `PreSampledTracer` is not implemented for `opentelemetry::sdk::trace::Tracer`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `PreSampledTracer`:
opentelemetry::sdk::trace::tracer::Tracer
opentelemetry::trace::noop::NoopTracer
= note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>` for `OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>`
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>` for `Option<OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>>`
note: required by a bound in `with`
--> /home/eric/.cargo/registry/src/github.com-1ecc6299db9ec823/tracing-subscriber-0.3.15/src/layer/mod.rs:1440:12
|
1440 | L: Layer<Self>,
| ^^^^^^^^^^^ required by this bound in `with`
error[E0277]: the trait bound `opentelemetry::sdk::trace::Tracer: opentelemetry::trace::tracer::Tracer` is not satisfied
--> rss-common/src/observability.rs:7:60
|
7 | pub fn get_subscriber(name: String, env_filter: String) -> impl Subscriber + Sync + Send {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `opentelemetry::trace::tracer::Tracer` is not implemented for `opentelemetry::sdk::trace::Tracer`
|
= help: the following other types implement trait `opentelemetry::trace::tracer::Tracer`:
opentelemetry::global::trace::BoxedTracer
opentelemetry::sdk::trace::tracer::Tracer
opentelemetry::trace::noop::NoopTracer
= note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>` for `OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>`
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>` for `Option<OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>>`
= note: required because of the requirements on the impl of `tracing::Subscriber` for `Layered<Option<OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>>, Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>`
error[E0277]: the trait bound `opentelemetry::sdk::trace::Tracer: PreSampledTracer` is not satisfied
--> rss-common/src/observability.rs:7:60
|
7 | pub fn get_subscriber(name: String, env_filter: String) -> impl Subscriber + Sync + Send {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PreSampledTracer` is not implemented for `opentelemetry::sdk::trace::Tracer`
|
= help: the following other types implement trait `PreSampledTracer`:
opentelemetry::sdk::trace::tracer::Tracer
opentelemetry::trace::noop::NoopTracer
= note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>` for `OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>`
= note: 1 redundant requirement hidden
= note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>` for `Option<OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>>`
= note: required because of the requirements on the impl of `tracing::Subscriber` for `Layered<Option<OpenTelemetryLayer<Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, opentelemetry::sdk::trace::Tracer>>, Layered<SentryLayer<Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>, Layered<BunyanFormattingLayer<fn() -> Stdout {stdout}>, Layered<JsonStorageLayer, Layered<EnvFilter, Registry>>>>>`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `rss-common` due to 6 previous errors
I looked at the change log of the said crates, and find nothing obvious about what I should change to make it compile again
What should I change?

Simple. You're using tracing-opentelemetry to connect the tracing and opentelemetry ecosystems, but the crate has not been updated to support v0.18 of opentelementry as of yet. Without this layer of functionality, you cannot update to the latest opentelemetry version, unless you want to forgo tracing integration.
I see the developers have merged in support for the latest version, but it appears to have not been published yet. Be patient. :)

Related

Vector of async functions that receives arguments passed by reference

I want to create a vector of async functions, but it only works with the 'static lifetime:
use std::future::Future;
use std::pin::Pin;
type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
type SimpleHandler = Box<dyn Fn(&u32, &u64) -> BoxFuture<Option<String>>>;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let v: Vec<SimpleHandler> = vec![
Box::new(|a, b| Box::pin(handle_create_group(a, b))),
Box::new(|a, b| Box::pin(handle_drop_group(a, b))),
];
for f in &v {
println!("{:?}", (f)(&0, &0).await);
}
Ok(())
}
async fn handle_create_group(a: &u32, b: &u64) -> Option<String> {
Some("hello".into())
}
async fn handle_drop_group(a: &u32, b: &u64) -> Option<String> {
Some("world".into())
}
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter '_ in function call due to conflicting requirements
--> src/main.rs:10:34
|
10 | Box::new(|a, b| Box::pin(handle_create_group(a, b))),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 10:18...
--> src/main.rs:10:18
|
10 | Box::new(|a, b| Box::pin(handle_create_group(a, b))),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:10:54
|
10 | Box::new(|a, b| Box::pin(handle_create_group(a, b))),
| ^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
--> src/main.rs:10:25
|
10 | Box::new(|a, b| Box::pin(handle_create_group(a, b))),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = std::option::Option<std::string::String>> + 'static)>>`
found `std::pin::Pin<std::boxed::Box<dyn std::future::Future<Output = std::option::Option<std::string::String>>>>`
Can I set the future's lifetime to be bound to the argument lifetime?
I found solution:
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
type SimpleHandler = Box<dyn for<'a> Fn(&'a u32, &'a u64) -> BoxFuture<'a, Option<String>>>;

How to join_all from a Vec of closures that return asyncs?

I want to generate a Vec of .awaits and execute them with join_all:
use futures::future::join_all; // 0.3.5
use std::future::Future;
async fn hello(name: &str) -> String {
format!("Hello {}!", name)
}
async fn main() {
let urls = vec!["Peter", "Hans", "Jake"];
let mut requests: Vec<Box<dyn Fn() -> Box<dyn Future<Output = String>>>> = vec![];
for url in urls {
requests.push(Box::new(|| Box::new(hello(&url))));
}
let responses: Vec<String> = join_all(requests).await;
println!("Response: {:?}", responses);
}
I get the error message:
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` cannot be unpinned
--> src/main.rs:15:45
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.5/src/future/join_all.rs:83:14
|
83 | I::Item: Future,
| ------ required by this bound in `futures::future::join_all`
|
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
--> src/main.rs:15:45
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^ `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.5/src/future/join_all.rs:83:14
|
83 | I::Item: Future,
| ------ required by this bound in `futures::future::join_all`
|
= help: the trait `futures::Future` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` cannot be unpinned
--> src/main.rs:15:36
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.5/src/future/join_all.rs:28:8
|
28 | F: Future,
| ------ required by this bound in `futures::future::JoinAll`
|
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
--> src/main.rs:15:36
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^^^^^^^^^^^ `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.5/src/future/join_all.rs:28:8
|
28 | F: Future,
| ------ required by this bound in `futures::future::JoinAll`
|
= help: the trait `futures::Future` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` cannot be unpinned
--> src/main.rs:15:36
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
|
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
--> src/main.rs:15:36
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^^^^^^^^^^^^^^^^^ `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
|
= help: the trait `futures::Future` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `main` has invalid return type `impl futures::Future`
--> src/main.rs:9:17
|
9 | async fn main() {
| ^ `main` can only return types that implement `std::process::Termination`
|
= help: consider using `()`, or a `Result`
error[E0752]: `main` function is not allowed to be `async`
--> src/main.rs:9:1
|
9 | async fn main() {
| ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async`
join_all requires an iterator of futures, not an iterator of functions returning futures:
pub fn join_all<I>(i: I) -> JoinAll<<I as IntoIterator>::Item>
where
I: IntoIterator,
<I as IntoIterator>::Item: Future,
Additionally, your futures can't be pinned and so join_all cannot use them.
The shortest fix is to:
Call the closure
Pin the future
use futures::future; // 0.3.5
use std::{future::Future, pin::Pin};
async fn hello(name: &str) -> String {
format!("Hello {}!", name)
}
pub async fn example() {
let urls = vec!["Peter", "Hans", "Jake"];
let mut requests: Vec<Box<dyn Fn() -> Pin<Box<dyn Future<Output = String>>>>> = vec![];
for url in urls {
requests.push(Box::new(move || Box::pin(hello(&url))));
}
let responses: Vec<String> = future::join_all(requests.into_iter().map(|r| r())).await;
println!("Response: {:?}", responses);
}
This can be written more succinctly as:
use futures::future::{self, FutureExt, LocalBoxFuture}; // 0.3.5
async fn hello(name: &str) -> String {
format!("Hello {}!", name)
}
pub async fn example() {
let urls = vec!["Peter", "Hans", "Jake"];
let mut requests: Vec<Box<dyn Fn() -> LocalBoxFuture<'static, String>>> = vec![];
for url in urls {
requests.push(Box::new(move || hello(&url).boxed_local()));
}
let responses: Vec<String> = future::join_all(requests.into_iter().map(|r| r())).await;
println!("Response: {:?}", responses);
}
However, none of that is needed for your specific example:
The closure doesn't provide any value
You have one type of future so there's no need for dynamic dispatch
You don't even need a Vec
use futures::future; // 0.3.5
async fn hello(name: &str) -> String {
format!("Hello {}!", name)
}
pub async fn example() {
let urls = vec!["Peter", "Hans", "Jake"];
let hellos = urls.iter().map(|u| hello(u));
let responses = future::join_all(hellos).await;
println!("Response: {:?}", responses);
}
See also:
How can I put an async function into a map in Rust?
Cannot use `impl Future` to store async function in a vector

How to use a `Stream` object inside the closure of `for_each` future?

I have a structure which receives some websocket events. Here is a method to receive an event from the structure:
struct Connection;
impl Connection {
pub fn recv_event(&mut self) -> Result<Event> {
// ...
}
}
I have implemented Stream for it:
#[cfg(feature = "stream")]
impl Stream for Connection {
type Item = Event;
type Error = ::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
match self.recv_event() {
Ok(event) => Ok(Async::Ready(Some(event))),
Err(e) => Err(e),
}
}
}
It looks that it works okay, but later I decided to return a reference to Self also for being able to modify the object's state in this code:
connection.by_ref().for_each(|c, e| {
println!("Event: {:?}", e);
self.handle_events(c, e.clone());
self.handle_messages(e);
Ok(())
}).wait();
I need to return a reference to the connection object from the fn poll:
#[cfg(feature = "stream")]
impl Stream for Connection {
type Item = (&mut Self, Event);
type Error = ::Error;
fn poll<'a>(&'a mut self) -> Poll<Option<(&'a mut Self, Event)>, Self::Error> {
match self.recv_event() {
Ok(event) => Ok(Async::Ready(Some(self, event))),
Err(e) => Err(e),
}
}
}
Unfortunately, this does not work:
error[E0106]: missing lifetime specifier
--> src/connection.rs:410:18
|
410 | type Item = (&mut Self, Event);
| ^ expected lifetime parameter
Yes, I forgot to add a lifetime here, in the type. Oops. How can I do that? I tried that and some other ways but nothing worked:
#[cfg(feature = "stream")]
impl<'a> Stream for Connection {
type Item = (&'a mut Self, Event);
type Error = ::Error;
fn poll<'a>(&'a mut self) -> Poll<Option<(&'a mut Self, Event)>, Self::Error> {
match self.recv_event() {
Ok(event) => Ok(Async::Ready(Some(self, event))),
Err(e) => Err(e),
}
}
}
Which gives the error:
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/connection.rs:409:6
|
409 | impl<'a> Stream for Connection {
| ^^ unconstrained lifetime parameter
Then I tried:
pub struct ConnectionStream<'a>(&'a mut Connection);
#[cfg(feature = "stream")]
impl<'a> Stream for ConnectionStream<'a> {
type Item = (&'a mut Connection, Event);
type Error = ::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
let res = self.0.recv_event();
match res {
Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
Err(e) => Err(e),
}
}
}
But still no luck:
error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
--> src/connection.rs:417:42
|
417 | Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 414:64...
--> src/connection.rs:414:65
|
414 | fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
| _________________________________________________________________^ starting here...
415 | | let res = self.0.recv_event();
416 | | match res {
417 | | Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
418 | | Err(e) => Err(e),
419 | | }
420 | | }
| |_____^ ...ending here
note: ...so that reference does not outlive borrowed content
--> src/connection.rs:417:48
|
417 | Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
| ^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 414:64...
--> src/connection.rs:414:65
|
414 | fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
| _________________________________________________________________^ starting here...
415 | | let res = self.0.recv_event();
416 | | match res {
417 | | Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
418 | | Err(e) => Err(e),
419 | | }
420 | | }
| |_____^ ...ending here
note: ...so that types are compatible (expected futures::Stream, found futures::Stream)
--> src/connection.rs:414:65
|
414 | fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
| _________________________________________________________________^ starting here...
415 | | let res = self.0.recv_event();
416 | | match res {
417 | | Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
418 | | Err(e) => Err(e),
419 | | }
420 | | }
| |_____^ ...ending here
I gave up and I think it is impossible. Am I correct?

Cannot infer an appropriate lifetime for lifetime parameter while implementing Deref trait

I am trying to implement Deref for an enum:
use std::rc::Rc;
use std::ops::Deref;
pub trait tObject {
fn name(&self) -> String;
fn span(&self) -> u32;
}
pub struct t1 {
pub name: String,
pub bd: Option<String>,
pub span: u32,
pub label: Option<String>
}
pub struct t2 {
pub name: String,
pub vrf: Option<String>,
pub span: u32,
pub label: Option<String>,
pub svi: u32
}
pub struct t3 {
pub name: String,
pub span: u32,
pub label: Option<String>
}
impl tObject for t1 {
fn name(&self) -> String {self.name.clone()}
fn span(&self) -> u32 {self.span.clone()}
}
impl tObject for t2 {
fn name(&self) -> String {self.name.clone()}
fn span(&self) -> u32 {self.span.clone()}
}
impl tObject for t3 {
fn name(&self) -> String {self.name.clone()}
fn span(&self) -> u32 {self.span.clone()}
}
pub enum TType {
t1(Rc<t1>),
t2(Rc<t2>),
t3(Rc<t3>)
}
impl Deref for TType {
type Target = tObject;
fn deref<'a>(&'a self) -> &'a tObject {
match *self {
TType::t1(ref x) => x as &t1,
TType::t2(ref x) => x as &t2,
TType::t3(ref x) => x as &t3
}
}
}
fn main() {
let mut t1s: Vec<Rc<t1>> = Vec::new();
let mut t2s: Vec<Rc<t2>> = Vec::new();
let mut t3s: Vec<Rc<t3>> = Vec::new();
let t_iter: Box<Iterator<Item=TType>> = Box::new(t1s.iter().map(|x| TType::t1(x.clone())).chain(
t2s.iter().map(|x| TType::t2(x.clone())).chain(
t3s.iter().map(|x| TType::t3(x.clone())))));
}
The compiler reports this error:
rustc 1.15.1 (021bd294c 2017-02-08)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
--> <anon>:53:5
|
53 | fn deref<'a>(&'a self) -> &'a tObject {
| _____^ starting here...
54 | | match *self {
55 | | TType::t1(ref x) => x as &t1,
56 | | TType::t2(ref x) => x as &t2,
57 | | TType::t3(ref x) => x as &t3
58 | | }
59 | | }
| |_____^ ...ending here
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 53:42...
--> <anon>:53:43
|
53 | fn deref<'a>(&'a self) -> &'a tObject {
| ___________________________________________^ starting here...
54 | | match *self {
55 | | TType::t1(ref x) => x as &t1,
56 | | TType::t2(ref x) => x as &t2,
57 | | TType::t3(ref x) => x as &t3
58 | | }
59 | | }
| |_____^ ...ending here
note: ...so that method type is compatible with trait (expected fn(&TType) -> &tObject + 'static, found fn(&TType) -> &tObject)
--> <anon>:53:5
|
53 | fn deref<'a>(&'a self) -> &'a tObject {
| _____^ starting here...
54 | | match *self {
55 | | TType::t1(ref x) => x as &t1,
56 | | TType::t2(ref x) => x as &t2,
57 | | TType::t3(ref x) => x as &t3
58 | | }
59 | | }
| |_____^ ...ending here
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that method type is compatible with trait (expected fn(&TType) -> &tObject + 'static, found fn(&TType) -> &tObject)
--> <anon>:53:5
|
53 | fn deref<'a>(&'a self) -> &'a tObject {
| _____^ starting here...
54 | | match *self {
55 | | TType::t1(ref x) => x as &t1,
56 | | TType::t2(ref x) => x as &t2,
57 | | TType::t3(ref x) => x as &t3
58 | | }
59 | | }
| |_____^ ...ending here
If I make the return type of deref Self::Target instead of tObject, it compiles fine. I do not understand this behaviour.
Here is a MCVE. Programmers use these to help narrow down the scope of a problem. For example, this MCVE rules out anything being due to the use of the enum, the Rc, any of the methods in the trait, or any of the fields in the structs. This allows us to focus on what is important:
use std::ops::Deref;
pub trait Trait {}
pub struct S {}
impl Trait for S {}
pub struct Container(S);
impl Deref for Container {
type Target = Trait;
// fn deref(&self) -> &Trait { // Fails!
fn deref(&self) -> &Self::Target { // Works!
&self.0
}
}
From the code, we can intuit that, somehow, Trait and Self::Target are not the same type. It's a bit tricky to see the type here, but this code prints out the type as a compiler error:
fn deref(&self) -> &Self::Target {
let a: Self::Target;
&self.0
}
error[E0277]: the trait bound `Trait + 'static: std::marker::Sized` is not satisfied
We don't actually care about the error, but we've discovered the type: Trait + 'static. Let's see what happens if we try something like that:
fn deref(&self) -> &(Trait + 'static) {
&self.0
}
This compiles.
In case you are unfamiliar with this syntax, there are plenty of questions about it. Here are some:
Type definition with a trait: Differences of specifying an explicit lifetime bound?
Explicit lifetime declarations in trait objects held by structs

"consider removing this semicolon" error

While following the rustbyexample.com tutorial, I typed the following code:
impl fmt::Display for Structure {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let x = format!("{}", "something");
write!(f, "OMG! {}", self.0);
}
}
And got the following error from the compiler:
error[E0308]: mismatched types
--> src/main.rs:5:58
|
5 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
| __________________________________________________________^
6 | | let x = format!("{}", "something");
7 | | write!(f, "OMG! {}", self.0);
8 | | }
| |_____^ expected enum `std::result::Result`, found ()
|
= note: expected type `std::result::Result<(), std::fmt::Error>`
found type `()`
help: consider removing this semicolon:
--> src/main.rs:7:37
|
7 | write!(f, "OMG! {}", self.0);
| ^
Why is the semicolon relevant (or not) here?
The return value from a Rust function is the last expression not followed by a semicolon. With the semicolon, your method doesn't return anything. Without the last semicolon, it returns the value of write!(f, "OMG! {}", self.0).
You can read more about that in The Rust Programming Language chapter about functions; look for the part starting with "What about returning a value?".

Resources