1
votes

I'm trying to shorten a function signature by introducing a type alias. The type specification of the parameter looks like this

writer: Arc<Mutex<&mut (dyn AsyncWrite + Unpin + Send + Sync)>>  // working

which I thought could be shortened by introducing this type alias

pub type RefAsyncWriter<'a> = &'a mut (dyn AsyncWrite + Unpin + Send + Sync);

so the type parameter becomes just

writer: Arc<Mutex<RefAsyncWriter>>  // error[E0726]: implicit elided lifetime not allowed here

Unfortunately this change gets me into trouble with lifetimes.

Here I made a brief example

use tokio::io::AsyncWrite;
use tokio::fs::File;
use std::sync::{Arc,Mutex};
use std::path::PathBuf;
pub type RefAsyncWriter<'a> = &'a mut (dyn AsyncWrite + Unpin + Send + Sync);

#[tokio::main]
async fn main() {
    let f = File::create(PathBuf::from("/tmp/test.txt")).await.unwrap();
    w(Arc::new(Mutex::new(&mut f)));
}

async fn w(writer: Arc<Mutex<RefAsyncWriter>>) {
  // TODO
}

The result is the following

Compiling playground v0.0.1 (/playground)
error[E0726]: implicit elided lifetime not allowed here
  --> src/main.rs:13:31
   |
13 | async fn w (writer: Arc<Mutex<RefAsyncWriter>>) {}
   |                               ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`

error: aborting due to previous error

(see: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=eb46708a9df66efa0de419a8d98490cf)

If somebody could explain to me (1) if there is a way to get this working and maybe (2) why the type alias actually makes such a difference to the compiler that would be of great help.

Thanks a lot in advance.

1

1 Answers

3
votes

Since you introduce an explicit lifetime 'a in the type alias, you need to specify it when you use this type.

async fn w<'a>(writer: Arc<Mutex<RefAsyncWriter<'a>>>) {}

It seems to work in the playground you provided.

And as the compiler suggests, the anonymous litetime is equivalent.

async fn w(writer: Arc<Mutex<RefAsyncWriter<'_>>>) {}

The original version of your function (with the very long type written down after writer: is somewhat equivalent to print1(), print2() and print3() in this documentation. If you introduce a reference as parameter, then a lifetime parameter necessarily exists for this function; the elision brings just some comfort to save some keystrokes when no confusion is possible about this lifetime.

When defining a type alias containing a reference, the compiler wants us to make the lifetime explicit, probably to prevent someone using this type alias from forgetting that there is a reference hidden inside. Then, using this type alias requires the <'...> notation. But again, when no confusion is possible at usage, the anonymous lifetime <'_> saves some keystrokes, avoiding writing <'a> twice (after the function name, and in the parameter).