asomers / mockall

A powerful mock object library for Rust
Apache License 2.0
1.5k stars 62 forks source link

"error[E0637]: `&` without an explicit lifetime name cannot be used here" #398

Closed sutes closed 2 years ago

sutes commented 2 years ago

Version 0.11.2.

use {
    std::path::Path,
};

#[mockall::automock]
trait Test {
    fn test(&self) -> Result<&Path, std::io::Error>;
}

fn main() {
    let _ = MockTest::new();
}

produces:

error[E0637]: `&` without an explicit lifetime name cannot be used here
 --> src/main.rs:7:30
  |
7 |     fn test(&self) -> Result<&Path, std::io::Error>;
  |                              ^ explicit lifetime name needed here

error[E0106]: missing lifetime specifier
 --> src/main.rs:7:30
  |
7 |     fn test(&self) -> Result<&Path, std::io::Error>;
  |                              ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
  = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'a` lifetime
  |
5 ~ for<'a> #[mockall::automock]
6 | trait Test {
7 ~     fn test(&self) -> Result<&'a Path, std::io::Error>;
  |
help: consider using the `'static` lifetime
  |
7 |     fn test(&self) -> Result<&'static Path, std::io::Error>;
  |                              ~~~~~~~~

Workaround:

#[mockall::automock]
trait Test {
    fn test<'a>(&'a self) -> Result<&'a Path, std::io::Error>;
}
asomers commented 2 years ago

Does your workaround even work? I would expect it to fail when you try to set an expectation unless the lifetime is 'static. In general, crafting mock methods that return a struct with a lifetime parameter is very hard. I suggest a workaround like this:

mockall::mock!{
    Test {}
    impl Test for Test {
        fn test(&self) -> Result<&'static Path, std::io::Error>;
    }
}

Closing as duplicate of #387 .