`dyn XXX` had impl `Debug`, but `dyn XXX + Send` can't Debug.
I tried this code:
#[async_trait]
pub trait ConnectionDriver {
...
}
impl fmt::Debug for dyn ConnectionDriver {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
...
}
}
type C = Box<dyn ConnectionDriver + Send>;
pub struct Connection(C);
impl Connection {
pub fn new(c: C) -> Connection {
Connection(c)
}
}
impl Deref for Connection {
type Target = C;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Connection {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
fn main() {
let conn = Connection::new(Box::new());
println!("{:?}", conn);
}

Meta
rustc --version --verbose:
rustc 1.62.0-nightly (de1026a67 2022-04-23)
binary: rustc
commit-hash: de1026a67b0a3f5d6b61a1f77093af97d4799376
commit-date: 2022-04-23
host: x86_64-pc-windows-msvc
release: 1.62.0-nightly
LLVM version: 14.0.1
Backtrace
Compiling unmp-net v0.8.0 (D:\Desktop\crise\project\unmp\unmp.example.rust\unmp-net)
error[E0277]: `dyn unmp_link::connection::ConnectionDriver + core::marker::Send` doesn't implement `core::fmt::Debug`
--> unmp-net\src\conns.rs:60:57
|
60 | log::warn!("{:?} disconnected", conn.as_ref());
| ^^^^^^^^^^^^^ `dyn unmp_link::connection::ConnectionDriver + core::marker::Send` cannot be formatted using `{:?}` because it doesn't implement `core::fmt::Debug`
|
= help: the trait `core::fmt::Debug` is not implemented for `dyn unmp_link::connection::ConnectionDriver + core::marker::Send`
= help: the following other types implement trait `core::fmt::Debug`:
(dyn Any + 'static)
(dyn Any + Sync + core::marker::Send + 'static)
(dyn Any + core::marker::Send + 'static)
(dyn unmp_link::connection::ConnectionDriver + 'static)
(dyn unmp_link::listener::ListenerDriver + 'static)
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: `dyn unmp_link::connection::ConnectionDriver + core::marker::Send` doesn't implement `core::fmt::Debug`
--> unmp-net\src\conns.rs:28:38
|
28 | log::info!("{:?} connected", conn.as_ref());
| ^^^^^^^^^^^^^ `dyn unmp_link::connection::ConnectionDriver + core::marker::Send` cannot be formatted using `{:?}` because it doesn't implement `core::fmt::Debug`
|
= help: the trait `core::fmt::Debug` is not implemented for `dyn unmp_link::connection::ConnectionDriver + core::marker::Send`
= help: the following other types implement trait `core::fmt::Debug`:
(dyn Any + 'static)
(dyn Any + Sync + core::marker::Send + 'static)
(dyn Any + core::marker::Send + 'static)
(dyn unmp_link::connection::ConnectionDriver + 'static)
(dyn unmp_link::listener::ListenerDriver + 'static)
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0277`.
error: could not compile `unmp-net` due to 2 previous errors
warning: build failed, waiting for other jobs to finish...
You need to implement Debug for dyn ConnectionDriver + Send, which in this usage acts as a distinct type from dyn ConnectionDriver.
I can probably implement a better error message for this, though...
I think it should auto implement Debug for both dyn ConnectionDriver + Send and dyn ConnectionDriver + !Send.
@rise0chen, I think that would be a backwards-incompatible change with current behavior, because then these impls would overlap:
trait Bar {}
trait Foo {}
impl Foo for dyn Bar + Send {}
impl Foo for dyn Bar {}
impl Foo for dyn Bar + Send {} have a High priority.
impl Foo for dyn Bar {} have a Low priority.
And, dyn Bar + !Send auto impl Foo by impl Foo for dyn Bar {}
I think the problem here is that dyn A+B isn't a subset of dyn A. They are distinct types. This is different from trait bounds, where T: A+B is a subset of T: A. For trait bounds, we can implement something for A and expect it to be implemented for A+B; or if we want to have a different implementation for A+B, we have specialization for that. We probably need to overhaul the entire dyn type system to make it work in the way you want.
I think it is a similar problem.
#[async_trait(?Send)]
pub trait ListenerDriver {
async fn accept(&mut self) -> Result<Connection, RecvError>;
}
#[async_trait]
impl ListenerDriver for Server {
async fn accept(&mut self) -> Result<Connection, RecvError> {...}
}
error[E0053]: method `accept` has an incompatible type for trait
--> unmp-link-udp\src\server.rs:86:5
|
86 | async fn accept(&mut self) -> Result<Connection, RecvError> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Future<Output = Result<unmp_link::connection::Connection, unmp_link::error::RecvError>>`, found trait `Future<Output = Result<unmp_link::connection::Connection, unmp_link::error::RecvError>> + Send`
|
= note: expected fn pointer `fn(&'life0 mut server::Server) -> Pin<Box<(dyn Future<Output = Result<unmp_link::connection::Connection, unmp_link::error::RecvError>> + 'async_trait)>>`
found fn pointer `fn(&'life0 mut server::Server) -> Pin<Box<(dyn Future<Output = Result<unmp_link::connection::Connection, unmp_link::error::RecvError>> + Send + 'async_trait)>>`
For more information about this error, try `rustc --explain E0053`.
error: could not compile `unmp-link-udp` due to previous error
CC #119338 which would fix this I think.