I was trying to make a brief demo of a HTTP/HTTPS server, and came into a strange compiler error. I will show a simplified version of my code below to illustrate the problem.
First I'd like to create a Listener
trait, which will be implemented by stuff like TcpListener
or UdpListener
. The trait is simple:
trait Listener {
type Conn;
fn accept(&self) -> Self::Conn;
}
Next I want to make a TlsListener
. Considering a TLS connection should be based on an established TCP connection, it should contain an underlying Listener
, like:
struct TlsListener<Ln>
where
Ln: Listener,
{
ln: Ln,
}
Now I need to implement Listener
trait for it, and that's when error occurs. I will replace the actual accept
logic with some test code, and the lines commented with "not ok" will lead to an error:
fn test(_t: Pin<Box<dyn Unpin + 'static>>) {}
fn test_ref(_t: &Pin<Box<dyn Unpin + 'static>>) {}
impl<Ln> Listener for TlsListener<Ln>
where
Ln: Listener,
Ln::Conn: Unpin + 'static,
{
type Conn = ();
fn accept(&self) {
// ok
let conn = self.ln.accept();
test(Box::pin(conn));
// not ok
let conn1 = self.ln.accept();
test_ref(&Box::pin(conn1));
// ok
let conn2 = self.ln.accept();
let boxed_conn2 = Box::new(conn2);
test_ref(&Pin::new(boxed_conn2));
}
}
The error log is:
error[E0308]: mismatched types
--> src/main.rs:94:18
|
94 | test_ref(&Box::pin(conn1));
| -------- ^^^^^^^^^^^^^^^^ expected `&Pin<Box<dyn Unpin>>`, found `&Pin<Box<<Ln as Listener>::Conn>>`
| |
| arguments to this function are incorrect
|
= note: expected reference `&Pin<Box<(dyn Unpin + 'static)>>`
found reference `&Pin<Box<<Ln as Listener>::Conn>>`
note: function defined here
--> src/main.rs:108:4
|
108 | fn test_ref(_: &Pin<Box<dyn Unpin + 'static>>) {}
| ^^^^^^^^ ----------------------------------
help: consider constraining the associated type `<Ln as Listener>::Conn` to `(dyn Unpin + 'static)`
|
77 | Ln: Listener<Conn = (dyn Unpin + 'static)>,
| ++++++++++++++++++++++++++++++
For more information about this error, try `rustc --explain E0308`.
I wonder why it won't work after adding a reference, and why it becomes available again once I've seperated the Box
and Pin
operations.