I have two similar functions which run an HTTP server. run_http_server1() compiles without errors, but run_http_server2() has a generic specification which I cannot declare correctly and so I get compilation errors.
How do I declare the second function? Why does my declaration not work?
#[tokio::main]
async fn main() {
// run_http_server1().await;
run_http_server2::<MyService>().await;
}
async fn run_http_server1() {
let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 3333));
let make_service = hyper::service::make_service_fn(|_conn| async {
let svc = MyService::new("hello, world!".to_string());
Ok::<_, std::convert::Infallible>(svc)
});
let server = hyper::Server::bind(&addr).serve(make_service);
server.await.expect("server failed");
}
async fn run_http_server2<S>()
where
S: tower::Service<hyper::Request<hyper::Body>> + 'static + Send + Factory,
<S as tower::Service<hyper::Request<hyper::Body>>>::Error: Sync + Send + std::error::Error,
<S as tower::Service<hyper::Request<hyper::Body>>>::Future: std::marker::Send,
{
let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 3333));
let make_service = hyper::service::make_service_fn(|_conn| async {
let svc = S::new("hello, world!".to_string());
Ok::<_, std::convert::Infallible>(svc)
});
let server = hyper::Server::bind(&addr).serve(make_service);
server.await.expect("server failed");
}
#[derive(Clone)]
struct MyService {
s: String,
}
trait Factory {
fn new(s: String) -> Self;
}
impl Factory for MyService {
fn new(s: String) -> MyService {
MyService { s }
}
}
impl tower::Service<hyper::Request<hyper::Body>> for MyService {
type Response = hyper::Response<hyper::Body>;
type Error = std::convert::Infallible;
type Future = futures::future::Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(
&mut self,
_cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
std::task::Poll::Ready(Ok(()))
}
fn call(&mut self, _req: hyper::Request<hyper::Body>) -> Self::Future {
let resp = hyper::Response::new(hyper::Body::from(self.s));
futures::future::ready(Ok(resp))
}
}
Here are my dependencies from Cargo.toml:
[dependencies]
hyper = { version = "0.14", features = ["full"] }
rustls-pemfile = "0.3"
tokio = { version = "1", features = ["full"] }
tokio-rustls = "0.23"
tower = { version = "0.4", features = ["make"] }
tracing = "0.1"
tracing-subscriber = { version="0.3", features = ["env-filter"] }
futures-util = "0.3"
futures = "0.3"
rustls = "0.20"
The error:
Compiling trial v0.1.0 (/home/alek/projects/rust/trial)
error[E0271]: type mismatch resolving `<<S as Service<Request<Body>>>::Future as futures::Future>::Output == Result<Response<_>, _>`
--> src/main.rs:32:45
|
32 | let server = hyper::Server::bind(&addr).serve(make_service);
| ^^^^^ expected associated type, found struct `Response`
|
= note: expected enum `Result<<S as Service<Request<Body>>>::Response, <S as Service<Request<Body>>>::Error>`
found enum `Result<Response<_>, _>`
= help: consider constraining the associated type `<S as Service<Request<Body>>>::Response` to `Response<_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: required because of the requirements on the impl of `futures::Future` for `hyper::proto::h2::server::H2Stream<<S as Service<Request<Body>>>::Future, _>`
= note: required because of the requirements on the impl of `hyper::common::exec::ConnStreamExec<<S as Service<Request<Body>>>::Future, _>` for `hyper::common::exec::Exec`
error[E0271]: type mismatch resolving `<S as Service<Request<Body>>>::Response == Response<_>`
--> src/main.rs:32:45
|
32 | let server = hyper::Server::bind(&addr).serve(make_service);
| ^^^^^ expected associated type, found struct `Response`
|
= note: expected associated type `<S as Service<Request<Body>>>::Response`
found struct `Response<_>`
= help: consider constraining the associated type `<S as Service<Request<Body>>>::Response` to `Response<_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: required because of the requirements on the impl of `hyper::service::http::HttpService<Body>` for `S`
error[E0277]: the trait bound `hyper::common::exec::Exec: hyper::common::exec::ConnStreamExec<<S as Service<Request<Body>>>::Future, _>` is not satisfied
--> src/main.rs:33:5
|
33 | server.await.expect("server failed");
| ^^^^^^^^^^^^ the trait `hyper::common::exec::ConnStreamExec<<S as Service<Request<Body>>>::Future, _>` is not implemented for `hyper::common::exec::Exec`
|
= help: the following implementations were found:
<hyper::common::exec::Exec as hyper::common::exec::ConnStreamExec<F, B>>
= note: required because of the requirements on the impl of `futures::Future` for `hyper::server::conn::spawn_all::NewSvcTask<AddrStream, impl futures::Future, S, hyper::common::exec::Exec, hyper::server::conn::spawn_all::NoopWatcher>`
= note: required because of the requirements on the impl of `hyper::common::exec::NewSvcExec<AddrStream, impl futures::Future, S, hyper::common::exec::Exec, hyper::server::conn::spawn_all::NoopWatcher>` for `hyper::common::exec::Exec`
= note: 1 redundant requirements hidden
= note: required because of the requirements on the impl of `futures::Future` for `Server<AddrIncoming, hyper::service::make::MakeServiceFn<[closure#src/main.rs:27:56: 30:6]>>`
note: required by `futures::Future::poll`
--> /home/alek/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:99:5
|
99 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0271]: type mismatch resolving `<S as Service<Request<Body>>>::Response == Response<_>`
--> src/main.rs:33:5
|
33 | server.await.expect("server failed");
| ^^^^^^^^^^^^ expected struct `Response`, found associated type
|
= note: expected struct `Response<_>`
found associated type `<S as Service<Request<Body>>>::Response`
= help: consider constraining the associated type `<S as Service<Request<Body>>>::Response` to `Response<_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: required because of the requirements on the impl of `hyper::service::http::HttpService<Body>` for `S`
= note: required because of the requirements on the impl of `hyper::common::exec::NewSvcExec<AddrStream, impl futures::Future, S, hyper::common::exec::Exec, hyper::server::conn::spawn_all::NoopWatcher>` for `hyper::common::exec::Exec`
= note: required because of the requirements on the impl of `futures::Future` for `Server<AddrIncoming, hyper::service::make::MakeServiceFn<[closure#src/main.rs:27:56: 30:6]>>`
note: required by `futures::Future::poll`
--> /home/alek/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:99:5
|
99 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0271]: type mismatch resolving `<<S as Service<Request<Body>>>::Future as futures::Future>::Output == Result<Response<_>, _>`
--> src/main.rs:33:5
|
33 | server.await.expect("server failed");
| ^^^^^^^^^^^^ expected struct `Response`, found associated type
|
= note: expected enum `Result<Response<_>, _>`
found enum `Result<<S as Service<Request<Body>>>::Response, <S as Service<Request<Body>>>::Error>`
= help: consider constraining the associated type `<S as Service<Request<Body>>>::Response` to `Response<_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: required because of the requirements on the impl of `futures::Future` for `hyper::proto::h2::server::H2Stream<<S as Service<Request<Body>>>::Future, _>`
= note: required because of the requirements on the impl of `hyper::common::exec::ConnStreamExec<<S as Service<Request<Body>>>::Future, _>` for `hyper::common::exec::Exec`
= note: 1 redundant requirements hidden
= note: required because of the requirements on the impl of `futures::Future` for `Server<AddrIncoming, hyper::service::make::MakeServiceFn<[closure#src/main.rs:27:56: 30:6]>>`
note: required by `futures::Future::poll`
--> /home/alek/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:99:5
|
99 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
error: could not compile `trial` due to 5 previous errors
Related
I have constructed the following example. It is at least approximately minimal.
use std::ops::Mul;
trait Muls<Rhs>:
Mul<Rhs, Output = <Self as Muls<Rhs>>::Output>
+ for<'a> Mul<&'a Rhs, Output = <Self as Muls<Rhs>>::Output>
{
type Output;
}
impl<T, R, O> Muls<R> for T
where
T: Mul<R, Output = O>,
T: for<'a> Mul<&'a R, Output = O>,
{
type Output = O;
}
trait ScalarMulCore {
type Scalar;
fn scalar_mul(&self, rhs: &Self::Scalar) -> Self;
fn scalar_mul_in_place(&mut self, rhs: &Self::Scalar);
}
struct Wrap<T> {
x: T,
}
impl<T> ScalarMulCore for Wrap<T>
where
T: Muls<T, Output = T>,
for<'a> &'a T: Muls<T, Output = T>,
{
type Scalar = T;
fn scalar_mul(&self, rhs: &Self::Scalar) -> Self {
Self { x: (&self.x) * rhs }
}
fn scalar_mul_in_place(&mut self, rhs: &Self::Scalar) {
self.x = (&self.x) * rhs;
}
}
impl<T> Mul<<Wrap<T> as ScalarMulCore>::Scalar> for Wrap<T>
where
Wrap<T>: ScalarMulCore,
{
type Output = Wrap<T>;
fn mul(mut self, rhs: <Wrap<T> as ScalarMulCore>::Scalar) -> Self::Output {
<Wrap<T> as ScalarMulCore>::scalar_mul_in_place(&mut self, &rhs);
self
}
}
impl<T> Mul<<Wrap<T> as ScalarMulCore>::Scalar> for &Wrap<T>
where
Wrap<T>: ScalarMulCore,
{
type Output = Wrap<T>;
fn mul(self, rhs: <Wrap<T> as ScalarMulCore>::Scalar) -> Self::Output {
<Wrap<T> as ScalarMulCore>::scalar_mul(self, &rhs)
}
}
fn main() {
let a = Wrap::<isize> { x: 2 };
let b: isize = 3;
assert_eq!((a * b).x, 6);
}
Trying to compile this produces the following error message:
Compiling mwe v0.1.0 (/home/zistack/Projects/mwe)
error[E0275]: overflow evaluating the requirement `for<'a> &'a Simd<_, _>: Mul<Simd<_, _>>`
--> src/main.rs:47:56
|
47 | impl <T> Mul <<Wrap <T> as ScalarMulCore>::Scalar> for Wrap <T>
| ^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mwe`)
note: required for `&'a Simd<_, _>` to implement `for<'a> Muls<Simd<_, _>>`
--> src/main.rs:10:16
|
10 | impl <T, R, O> Muls <R> for T
| ^^^^^^^^ ^
11 | where
12 | T: Mul <R, Output = O>,
| ---------- unsatisfied trait bound introduced here
note: required for `Wrap<Simd<_, _>>` to implement `ScalarMulCore`
--> src/main.rs:29:10
|
29 | impl <T> ScalarMulCore for Wrap <T>
| ^^^^^^^^^^^^^ ^^^^^^^^
...
32 | for <'a> &'a T: Muls <T, Output = T>
| ---------- unsatisfied trait bound introduced here
= note: 62 redundant requirements hidden
= note: required for `Wrap<_>` to implement `ScalarMulCore`
error[E0275]: overflow evaluating the requirement `for<'a> &'a Simd<_, _>: Mul<Simd<_, _>>`
--> src/main.rs:59:56
|
59 | impl <T> Mul <<Wrap <T> as ScalarMulCore>::Scalar> for &Wrap <T>
| ^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mwe`)
note: required for `&'a Simd<_, _>` to implement `for<'a> Muls<Simd<_, _>>`
--> src/main.rs:10:16
|
10 | impl <T, R, O> Muls <R> for T
| ^^^^^^^^ ^
11 | where
12 | T: Mul <R, Output = O>,
| ---------- unsatisfied trait bound introduced here
note: required for `Wrap<Simd<_, _>>` to implement `ScalarMulCore`
--> src/main.rs:29:10
|
29 | impl <T> ScalarMulCore for Wrap <T>
| ^^^^^^^^^^^^^ ^^^^^^^^
...
32 | for <'a> &'a T: Muls <T, Output = T>
| ---------- unsatisfied trait bound introduced here
= note: 62 redundant requirements hidden
= note: required for `Wrap<_>` to implement `ScalarMulCore`
For more information about this error, try `rustc --explain E0275`.
error: could not compile `mwe` due to 2 previous errors
I am using the nightly build.
The this example is pretty close to some real code that I want to write, and functionally identical to some test code that has been giving me some trouble. Strangely enough, if you comment out the second implementation of Mul, it compiles without issue. I cannot get away with doing this in my real code.
Why on earth is rustc trying to see if Wrap <Simd <_, _>> implements ScalarMulCore? I never asked for that type. Even if I did, why would that cause rustc to hit the recursion limit? Also, why is rustc only doing this when I attempt to additionally implement Mul for &Wrap <T>?
I know I'm linking to my own comment here, but it would appear that this behavior is a long-standing bug in the rust compiler.
I am using the genawaiter crate for generator functions to implement
single-threaded "multitasking".
I have this code to create a new Thread, and pass a generator to it, but I am struggling
to find how to represent the impl Future type that gen!() returns.
use genawaiter::rc::{gen, Gen};
use genawaiter::yield_;
struct Thread {
function: genawaiter::rc::Gen<(), Option<Sprite>, /*What can go here?*/>,
}
struct Sprite {/*fields here*/}
fn main() {
let thread1 = Thread {
function: gen!({
let object: Option<&mut Sprite> = yield_!(());
// do stuff with `object`
println!("Hi");
}),
};
}
The type that the gen!() macro returns is.
genawaiter::rc::Gen<(),Option<Sprite>,impl Future<Output = ()>>
If I try to set this as the type of the function field, I get this error message:
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path
--> src/main.rs:20:55
|
20 | function: genawaiter::rc::Gen<(), Option<Sprite>, impl Future<Output = ()>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0562`.
error: could not compile `testing` due to previous error
struct EmptyFuture{}
impl Future for EmptyFuture {
type Output = ();
fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
std::task::Poll::Ready(())
}
}
If I try putting this EmptyFuture struct in the function field, it also does
not work, and I get this error message:
error[E0308]: mismatched types
--> src/main.rs:27:19
|
27 | function: gen!({
| ___________________^____-
| |___________________|
| ||
28 | || let object: Option<Sprite> = yield_!(());
29 | || println!("Hi");
30 | || }),
| ||_________-^ expected struct `EmptyFuture`, found opaque type
| |_________|
| the found `async` block
|
::: /home/calvin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:72:43
|
72 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
| ------------------------------- the found opaque type
|
= note: expected struct `genawaiter::rc::Gen<_, _, EmptyFuture>`
found struct `genawaiter::rc::Gen<_, _, impl Future<Output = ()>>`
= note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
The only semi-relavant thing I could find on stackoverflow was this,
but that is about a function /returning/ an opaque type.
How can I represent the opaque type in my struct? Also, does it make a difference
whether it is an empty type (impl Future<Output = ()>) or some other struct(impl Future<Output = SomeStruct>)?
Edit:
I tried Box<dyn Future<Output = ()>>, and got this error:
error[E0277]: `(dyn Future<Output = ()> + 'static)` cannot be unpinned
--> src/target/mod.rs:325:15
|
325 | function: genawaiter::rc::Gen<(), Option<Sprite>, Box<dyn Future<Output = ()>>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `(dyn Future<Output = ()> + 'static)`
|
= note: consider using `Box::pin`
= note: required because of the requirements on the impl of `Future` for `Box<(dyn Future<Output = ()> + 'static)>`
note: required by a bound in `genawaiter::rc::Gen`
--> /home/calvin/.cargo/registry/src/github.com-1ecc6299db9ec823/genawaiter-0.99.1/src/rc/generator.rs:11:25
|
11 | pub struct Gen<Y, R, F: Future> {
| ^^^^^^ required by this bound in `genawaiter::rc::Gen`
For more information about this error, try `rustc --explain E0277`.
I followed the compiler suggestion and changed it to
Pin<Box<dyn Future<Output = ()>>>, but now I am getting a
similar error as before:
error[E0308]: mismatched types
--> src/main.rs:28:19
|
28 | function: gen!({
| ___________________^____-
| |___________________|
| ||
29 | || let object: Option<Sprite> = yield_!(());
30 | || println!("Hi");
31 | || }),
| ||_________-^ expected struct `Pin`, found opaque type
| |_________|
| the found `async` block
|
::: /home/calvin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:72:43
|
72 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
| ------------------------------- the found opaque type
|
= note: expected struct `genawaiter::rc::Gen<_, _, Pin<Box<(dyn Future<Output = ()> + 'static)>>>`
found struct `genawaiter::rc::Gen<_, _, impl Future<Output = ()>>`
= note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0308`.
You could try boxing trait object. That is use Box<dyn Future<Output = ()>>. This will cost you an allocation per created future, but it's the simplest solution. And practically the only one if you don't (or can't) name a type.
How does one read and understand Rust traces with Opaque errors?
Example Error
For example, consider the following typically long error. How do you infer the problem from the error output?
error[E0599]: the method `next` exists for struct `Pin<&mut impl futures::Future<Output = AsyncStream<Result<u32, Box<dyn StdError>>, Opaque(DefId(0:51 ~ armadillo_rust[2000]::query_all::{opaque#0}::{opaque#0}), ['_#6r])>>>`, but its trait bounds were not satisfied
--> src/main.rs:198:31
|
198 | while let Some(x) = ticks.next().await {
| ^^^^ method cannot be called on `Pin<&mut impl futures::Future<Output = AsyncStream<Result<u32, Box<dyn StdError>>, Opaque(DefId(0:51 ~ armadillo_rust[2000]::query_all::{opaque#0}::{opaque#0}), ['_#6r])>>>` due to unsatisfied trait bounds
|
::: ../toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/pin.rs:408:1
|
408 | pub struct Pin<P> {
| -----------------
| |
| doesn't satisfy `_: StreamExt`
| doesn't satisfy `_: futures::Stream`
|
= note: the following trait bounds were not satisfied:
`Pin<&mut impl futures::Future<Output = AsyncStream<Result<u32, Box<dyn StdError>>, Opaque(DefId(0:51 ~ armadillo_rust[2000]::query_all::{opaque#0}::{opaque#0}), ['_#6r])>>>: futures::Stream`
which is required by `Pin<&mut impl futures::Future<Output = AsyncStream<Result<u32, Box<dyn StdError>>, Opaque(DefId(0:51 ~ armadillo_rust[2000]::query_all::{opaque#0}::{opaque#0}), ['_#6r])>>>: StreamExt`
`impl futures::Future<Output = AsyncStream<Result<u32, Box<dyn StdError>>, Opaque(DefId(0:51 ~ armadillo_rust[2000]::query_all::{opaque#0}::{opaque#0}), ['_#6r])>>: futures::Stream`
which is required by `impl futures::Future<Output = AsyncStream<Result<u32, Box<dyn StdError>>, Opaque(DefId(0:51 ~ armadillo_rust[2000]::query_all::{opaque#0}::{opaque#0}), ['_#6r])>>: StreamExt`
Minimal, Working Example:
use futures::StreamExt;
use async_stream::AsyncStream;
async fn query_all<'a>(date: &'a str) -> AsyncStream<Result<u32, Box<dyn std::error::Error + 'a>>, impl futures::Future + 'a> {
todo!();
}
#[tokio::main]
async fn main() {
let ticks = query_all("2022-06-14");
futures::pin_mut!(ticks);
while let Some(x) = ticks.next().await {
println!("{:?}", x);
}
}
Naive Solution
The error seems to be saying two things:
A pinned stream doesn't satisfy necessary bounds
The return type of query_all fails to implement certain traits.
However, confusingly, the exact same types work in this minimal example:
#[tokio::main]
async fn main() {
let ticks = stream! {
yield Ok(0);
yield Err("");
};
futures::pin_mut!(ticks);
while let Some(x) = ticks.next().await {
println!("{:?}", x);
}
}
How am I misreading this and what is Rust really trying to say?
I have the following trait and generic implementation for Fn:
trait Provider<'a> {
type Out;
fn get(&'a self, state: &State) -> Self::Out;
}
impl<'a, F, T> Provider<'a> for F
where
F: Fn(&State) -> T,
{
type Out = T;
fn get(&'a self, state: &State) -> T {
self(state)
}
}
Now, I have some code that wants a for<'a> Provider<'a, Out = usize>. However, the most simple closure, |_| 1, does not qualify and instead provides this error message which I don't understand:
fn assert_usize_provider<P>(_: P)
where
P: for<'a> Provider<'a, Out = usize>,
{
}
fn main() {
assert_usize_provider(|_| 1);
}
error[E0308]: mismatched types
--> src/main.rs:27:5
|
27 | assert_usize_provider(|_| 1);
| ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `FnOnce<(&State,)>`
found type `FnOnce<(&State,)>`
note: this closure does not fulfill the lifetime requirements
--> src/main.rs:27:27
|
27 | assert_usize_provider(|_| 1);
| ^^^^^
note: the lifetime requirement is introduced here
--> src/main.rs:22:29
|
22 | P: for<'a> Provider<'a, Out = usize>,
| ^^^^^^^^^^^
Playground link
Can someone explain what that error message means and how to get this code working?
I don't know why inference does not work in this case but you can add type annotation to get the code working.
assert_usize_provider(|_ : &State| 1);
Here is a contrived example of what I am trying to do:
use std::boxed::Box;
#[derive(Debug)]
pub struct Foo<'a>(pub &'a str);
pub trait IntoBox {
fn into_box<'a>(self) -> Box<Fn(Foo) -> String>;
}
impl<B> IntoBox for B where B: Fn(Foo) -> String + 'static {
fn into_box(self) -> Box<Fn(Foo) -> String> { Box::new(self) }
}
fn direct_into_box<B: Fn(Foo) -> String + 'static>(b: B) -> Box<Fn(Foo) -> String> {
Box::new(b)
}
fn main() {
// Doesn't work
let x = IntoBox::into_box(|i| format!("{:?}", i) );
// Works
let y = IntoBox::into_box(|i: Foo| format!("{:?}", i) );
// Also works
let z = direct_into_box(|i| format!("{:?}", i) );
}
How do I get my trait impl to do the same evaluation of the closure as is done by my direct_into_box? I would have expected direct_into_box and my trait impl to behave in the same way.
The error on x:
error[E0271]: type mismatch resolving `for<'r> <[closure#<anon>:20:31: 20:53] as std::ops::FnOnce<(Foo<'r>,)>>::Output == std::string::String`
--> <anon>:20:13
|
20 | let x = IntoBox::into_box(|i| format!("{:?}", i) );
| ^^^^^^^^^^^^^^^^^ expected bound lifetime parameter , found concrete lifetime
|
= note: concrete lifetime that was found is lifetime '_#29r
= note: required because of the requirements on the impl of `IntoBox` for `[closure#<anon>:20:31: 20:53]`
= note: required by `IntoBox::into_box`
error[E0281]: type mismatch: the type `[closure#<anon>:20:31: 20:53]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(Foo<'r>,)>` is required (expected concrete lifetime, found bound lifetime parameter )
--> <anon>:20:13
|
20 | let x = IntoBox::into_box(|i| format!("{:?}", i) );
| ^^^^^^^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `IntoBox` for `[closure#<anon>:20:31: 20:53]`
= note: required by `IntoBox::into_box`
Sounds like an inference bug in the compiler. What seems to happen is that the compiler implements Fn(Foo<'x>) for one specific lifetime 'x instead of Fn(Foo<'a>) for any lifetime 'a on your closure.
Let's see if we can replicate the error by defining a struct by hand (this requires a nightly compiler), so we can better understand what's going on. First, let's define the struct the correct way:
#![feature(fn_traits)]
#![feature(unboxed_closures)]
// Foo and IntoBox unchanged
struct Func;
impl<'a> FnOnce<(Foo<'a>,)> for Func {
type Output = String;
extern "rust-call" fn call_once(self, args: (Foo<'a>,)) -> String {
self.call(args)
}
}
impl<'a> FnMut<(Foo<'a>,)> for Func {
extern "rust-call" fn call_mut(&mut self, args: (Foo<'a>,)) -> String {
self.call(args)
}
}
impl<'a> Fn<(Foo<'a>,)> for Func {
extern "rust-call" fn call(&self, (i,): (Foo<'a>,)) -> String {
format!("{:?}", i)
}
}
fn main() {
let x = IntoBox::into_box(Func);
}
This Func struct compiles fine and behaves just like your original closure.
Now, let's break it:
impl FnOnce<(Foo<'static>,)> for Func {
type Output = String;
extern "rust-call" fn call_once(self, args: (Foo<'static>,)) -> String {
self.call(args)
}
}
impl FnMut<(Foo<'static>,)> for Func {
extern "rust-call" fn call_mut(&mut self, args: (Foo<'static>,)) -> String {
self.call(args)
}
}
impl Fn<(Foo<'static>,)> for Func {
extern "rust-call" fn call(&self, (i,): (Foo<'static>,)) -> String {
format!("{:?}", i)
}
}
What I've done here is that I've removed the <'a> on each impl, so that the impls are no longer generic over a lifetime, and I've replaced Foo<'a> with Foo<'static>. This means that now, the traits are only implemented when the "closure"'s argument is a Foo<'static>.
This fails to compile with the following errors:
error[E0271]: type mismatch resolving `for<'r> <Func as std::ops::FnOnce<(Foo<'r>,)>>::Output == std::string::String`
--> <anon>:51:13
|
51 | let x = IntoBox::into_box(Func);
| ^^^^^^^^^^^^^^^^^ expected bound lifetime parameter , found concrete lifetime
|
= note: concrete lifetime that was found is the static lifetime
= note: required because of the requirements on the impl of `IntoBox` for `Func`
= note: required by `IntoBox::into_box`
error[E0277]: the trait bound `for<'r> Func: std::ops::Fn<(Foo<'r>,)>` is not satisfied
--> <anon>:51:13
|
51 | let x = IntoBox::into_box(Func);
| ^^^^^^^^^^^^^^^^^ the trait `for<'r> std::ops::Fn<(Foo<'r>,)>` is not implemented for `Func`
|
= help: the following implementations were found:
= help: <Func as std::ops::Fn<(Foo<'static>,)>>
= note: required because of the requirements on the impl of `IntoBox` for `Func`
= note: required by `IntoBox::into_box`
The first error is the same, but instead of an internal name like '_#29r, the compiler mentions the static lifetime, because that's what I used here. I suspect that what the compiler is doing with the closure that doesn't compile in your code is similar to my second set of impls, just that instead of 'static, it's some other concrete lifetime that we can't name in Rust. The second error is different but means pretty much the same thing.