Rocket
Rocket copied to clipboard
DefaultListener::bindable() isn’t usable
Rocket Version
0.6.0 rev f75fb63
Operating System
Fedora Linux 39
Rust Toolchain Version
rustc 1.78.0-nightly (2bf78d12d 2024-02-18) and rustc 1.76.0 (07dca489a 2024-02-04)
What happened?
A low-level connection interface has been added in #1070 which I’m trying to use to implement more advanced TLS support. I’ve hit a roadblock however, as Rust won’t let me use the Bindable
returned by DefaultListener::bindable()
. I’ve been unable to find a work-around other than making DefaultListener::base_bindable()
public or making DefaultListener::bindable()
return Either<TlsBindable<std::net::SocketAddr>, TlsBindable<super::unix::UdsConfig>>
explicitly instead of impl Binding
. It is my understanding that the latter shouldn’t have any impact, but for some reason it does.
Note that having DefaultListener::base_bindable()
public would be helpful regardless. Currently I have to remove TLS configuration from DefaultListener
to make sure it won’t give me a TLS bindable.
Test Case
#[rocket::main]
async fn main() -> Result<(), rocket::Error> {
let rocket = rocket::build();
let config = rocket
.figment()
.extract::<rocket::listener::DefaultListener>()?;
rocket.launch_on(config.bindable()?).await?;
Ok(())
}
Log Output
error[E0277]: `impl std::future::Future<Output = Result<<impl Bindable as Bindable>::Listener, <impl Bindable as Bindable>::Error>>` cannot be sent between threads safely
--> src/main.rs:2:46
|
2 | async fn main() -> Result<(), rocket::Error> {
| ______________________________________________^
3 | | let rocket = rocket::build();
4 | | let config = rocket.figment().extract::<rocket::listener::DefaultListener>()?;
5 | | rocket.launch_on(config.bindable()?)
6 | | .await?;
7 | | Ok(())
8 | | }
| | ^
| | |
| |_`impl std::future::Future<Output = Result<<impl Bindable as Bindable>::Listener, <impl Bindable as Bindable>::Error>>` cannot be sent between threads safely
| within this `{async block@src/main.rs:2:46: 8:2}`
|
= help: within `{async block@src/main.rs:2:46: 8:2}`, the trait `std::marker::Send` is not implemented for `impl std::future::Future<Output = Result<<impl Bindable as Bindable>::Listener, <impl Bindable as Bindable>::Error>>`, which is required by `{async block@src/main.rs:2:46: 8:2}: std::marker::Send`
note: `<impl Bindable as Bindable>::bind` is an `async fn` in trait, which does not automatically imply that its future is `std::marker::Send`
--> Rocket/core/lib/src/listener/bindable.rs:10:5
|
10 | async fn bind(self) -> Result<Self::Listener, Self::Error>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `Rocket<Ignite>`, `impl std::future::Future<Output = Result<<impl Bindable as Bindable>::Listener, <impl Bindable as Bindable>::Error>>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`
note: required because it's used within this `async` fn body
--> Rocket/core/lib/src/rocket.rs:690:90
|
690 | async fn _launch_on<B: Bindable>(self, bindable: B) -> Result<Rocket<Ignite>, Error> {
| __________________________________________________________________________________________^
691 | | let listener = bindable.bind().await.map_err(|e| ErrorKind::Bind(Box::new(e)))?;
692 | | self.serve(listener).await
693 | | }
| |_____^
= note: required because it captures the following types: `Rocket<Build>`, `impl Bindable`, `rocket::phase::State`, `ControlFlow<Result<Infallible, rocket::Error>, Rocket<Ignite>>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`
note: required because it's used within this `async` fn body
--> Rocket/core/lib/src/rocket.rs:944:93
|
944 | pub async fn launch_on<B: Bindable>(self, bindable: B) -> Result<Rocket<Ignite>, Error> {
| _____________________________________________________________________________________________^
945 | | match self.0.into_state() {
946 | | State::Build(s) => Rocket::from(s).ignite().await?._launch_on(bindable).await,
947 | | State::Ignite(s) => Rocket::from(s)._launch_on(bindable).await,
948 | | State::Orbit(s) => Ok(Rocket::from(s).into_ignite())
949 | | }
950 | | }
| |_____^
= note: required because it captures the following types: `Rocket<Build>`, `DefaultListener`, `ControlFlow<Result<Infallible, rocket::Error>, impl Bindable>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`
note: required because it's used within this `async` block
--> src/main.rs:2:46
|
2 | async fn main() -> Result<(), rocket::Error> {
| ______________________________________________^
3 | | let rocket = rocket::build();
4 | | let config = rocket.figment().extract::<rocket::listener::DefaultListener>()?;
5 | | rocket.launch_on(config.bindable()?)
6 | | .await?;
7 | | Ok(())
8 | | }
| |_^
note: required by a bound in `async_main`
--> Rocket/core/lib/src/lib.rs:252:66
|
252 | pub fn async_main<R>(fut: impl std::future::Future<Output = R> + Send) -> R {
| ^^^^ required by this bound in `async_main`
error[E0277]: `impl std::future::Future<Output = Result<<<impl Bindable as Bindable>::Listener as Listener>::Accept, std::io::Error>>` cannot be sent between threads safely
--> src/main.rs:2:46
|
2 | async fn main() -> Result<(), rocket::Error> {
| ______________________________________________^
3 | | let rocket = rocket::build();
4 | | let config = rocket.figment().extract::<rocket::listener::DefaultListener>()?;
5 | | rocket.launch_on(config.bindable()?)
6 | | .await?;
7 | | Ok(())
8 | | }
| | ^
| | |
| |_`impl std::future::Future<Output = Result<<<impl Bindable as Bindable>::Listener as Listener>::Accept, std::io::Error>>` cannot be sent between threads safely
| within this `{async block@src/main.rs:2:46: 8:2}`
|
= help: within `{async block@src/main.rs:2:46: 8:2}`, the trait `std::marker::Send` is not implemented for `impl std::future::Future<Output = Result<<<impl Bindable as Bindable>::Listener as Listener>::Accept, std::io::Error>>`, which is required by `{async block@src/main.rs:2:46: 8:2}: std::marker::Send`
note: `<<impl Bindable as Bindable>::Listener as Listener>::accept` is an `async fn` in trait, which does not automatically imply that its future is `std::marker::Send`
--> Rocket/core/lib/src/listener/listener.rs:13:5
|
13 | async fn accept(&self) -> io::Result<Self::Accept>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `&listener::bounced::Bounced<<impl Bindable as Bindable>::Listener>`, `Result<<<impl Bindable as Bindable>::Listener as Listener>::Accept, std::io::Error>`, `impl std::future::Future<Output = Result<<<impl Bindable as Bindable>::Listener as Listener>::Accept, std::io::Error>>`, `std::io::Error`, `Sleep`
note: required because it's used within this `async` fn body
--> Rocket/core/lib/src/listener/bounced.rs:28:67
|
28 | pub async fn accept_next(&self) -> <Self as Listener>::Accept {
| ___________________________________________________________________^
29 | | loop {
30 | | match self.listener.accept().await {
31 | | Ok(accept) => return accept,
... |
38 | | }
39 | | }
| |_____^
= note: required because it captures the following types: `impl std::future::Future<Output = <listener::bounced::Bounced<<impl Bindable as Bindable>::Listener> as Listener>::Accept>`, `rocket::futures::future::Select<Pin<&mut impl std::future::Future<Output = <listener::bounced::Bounced<<impl Bindable as Bindable>::Listener> as Listener>::Accept>>, rocket::Shutdown>`
note: required because it's used within this `async` fn body
--> Rocket/core/lib/src/listener/cancellable.rs:111:75
|
111 | pub async fn accept_next(&self) -> Option<<Self as Listener>::Accept> {
| ___________________________________________________________________________^
112 | | let next = std::pin::pin!(self.listener.accept_next());
113 | | match select(next, self.trigger.clone()).await {
114 | | Either::Left((next, _)) => Some(next),
115 | | Either::Right(_) => None,
116 | | }
117 | | }
| |_____^
= note: required because it captures the following types: `Rocket<Ignite>`, `hyper_util::server::conn::auto::Builder<hyper_util::rt::tokio::TokioExecutor>`, `std::time::Duration`, `listener::cancellable::CancellableListener<rocket::Shutdown, listener::bounced::Bounced<<impl Bindable as Bindable>::Listener>>`, `Arc<Rocket<Orbit>>`, `rocket::tokio::task::JoinHandle<()>`, `Arc<hyper_util::server::conn::auto::Builder<hyper_util::rt::tokio::TokioExecutor>>`, `Arc<listener::cancellable::CancellableListener<rocket::Shutdown, listener::bounced::Bounced<<impl Bindable as Bindable>::Listener>>>`, `impl std::future::Future<Output = std::option::Option<<listener::cancellable::CancellableListener<rocket::Shutdown, listener::bounced::Bounced<<impl Bindable as Bindable>::Listener>> as Listener>::Accept>>`, `std::array::IntoIter<std::time::Duration, 5>`, `Sleep`
note: required because it's used within this `async` fn body
--> Rocket/core/lib/src/server.rs:89:5
|
89 | / {
90 | | let mut builder = Builder::new(TokioExecutor::new());
91 | | let keep_alive = Duration::from_secs(self.config.keep_alive.into());
92 | | builder.http1()
... |
178 | | }
179 | | }
| |_____^
= note: required because it captures the following types: `Rocket<Ignite>`, `impl std::future::Future<Output = Result<<impl Bindable as Bindable>::Listener, <impl Bindable as Bindable>::Error>>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`
note: required because it's used within this `async` fn body
--> Rocket/core/lib/src/rocket.rs:690:90
|
690 | async fn _launch_on<B: Bindable>(self, bindable: B) -> Result<Rocket<Ignite>, Error> {
| __________________________________________________________________________________________^
691 | | let listener = bindable.bind().await.map_err(|e| ErrorKind::Bind(Box::new(e)))?;
692 | | self.serve(listener).await
693 | | }
| |_____^
= note: required because it captures the following types: `Rocket<Build>`, `impl Bindable`, `rocket::phase::State`, `ControlFlow<Result<Infallible, rocket::Error>, Rocket<Ignite>>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`
note: required because it's used within this `async` fn body
--> Rocket/core/lib/src/rocket.rs:944:93
|
944 | pub async fn launch_on<B: Bindable>(self, bindable: B) -> Result<Rocket<Ignite>, Error> {
| _____________________________________________________________________________________________^
945 | | match self.0.into_state() {
946 | | State::Build(s) => Rocket::from(s).ignite().await?._launch_on(bindable).await,
947 | | State::Ignite(s) => Rocket::from(s)._launch_on(bindable).await,
948 | | State::Orbit(s) => Ok(Rocket::from(s).into_ignite())
949 | | }
950 | | }
| |_____^
= note: required because it captures the following types: `Rocket<Build>`, `DefaultListener`, `ControlFlow<Result<Infallible, rocket::Error>, impl Bindable>`, `impl std::future::Future<Output = Result<Rocket<Ignite>, rocket::Error>>`
note: required because it's used within this `async` block
--> src/main.rs:2:46
|
2 | async fn main() -> Result<(), rocket::Error> {
| ______________________________________________^
3 | | let rocket = rocket::build();
4 | | let config = rocket.figment().extract::<rocket::listener::DefaultListener>()?;
5 | | rocket.launch_on(config.bindable()?)
6 | | .await?;
7 | | Ok(())
8 | | }
| |_^
note: required by a bound in `async_main`
--> Rocket/core/lib/src/lib.rs:252:66
|
252 | pub fn async_main<R>(fut: impl std::future::Future<Output = R> + Send) -> R {
| ^^^^ required by this bound in `async_main`
For more information about this error, try `rustc --explain E0277`.
Additional Context
No response
System Checks
- [X] My bug report relates to functionality.
- [X] I have tested against the latest Rocket release or a recent git commit.
- [X] I have tested against the latest stable
rustc
toolchain. - [X] I was unable to find this issue previously reported.