nrxus / faux

Struct mocking library for Rust
https://nrxus.github.io/faux/
MIT License
411 stars 14 forks source link

borrowed value does not live long enough #22

Closed wcampbell0x2a closed 4 years ago

wcampbell0x2a commented 4 years ago

Looking into this mocking library, still relatively new to rust. Having some issues when trying to mock some object that I have that communicates with a unix socket.

Creating a mock function and this is the following code in my test file.

        let mut conn = Connection::faux();

        faux::when!(conn.run_command).safe_then(|_| Ok(()));

this is the function that is being mocked.

#[faux::create]
#[derive(Debug)]
pub struct Connection {
    stream: TcpStream,
}
#[faux::methods]
impl Connection {
    pub fn run_command(&mut self, command: &str) -> Result<()> {
    // read write
    }
}

this is the error when I try and compile the code.

error[E0597]: `conn` does not live long enough
  --> tests/client.rs:9:21
   |
4  | |
   | |__________________________________________________- argument requires that `conn` is borrowed for `'static`
...
9  |           faux::when!(conn.run_command).safe_then(|_| Ok(()));
   |                       -^^^
   |                       |
   |  _____________________borrowed value does not live long enough
   | |
...
13 |       }
   |       - `conn` dropped here while still borrowed

error: aborting due to previous error

Slightly confused about this error, because of the functions being called normally before trying out this library.

Thanks for the library, just need some explanation on how to fix this code.

wcampbell0x2a commented 4 years ago

never mind, just needed to use unsafe.

thedodd commented 4 years ago

It is a bit unfortunate that unsafe is needed in this seemingly standard use case. I haven't looked at the code yet, but it would seem that some better lifetime management would resolve the issue. Thoughts?

nrxus commented 3 years ago

It's both a limitation of the library and a limitation of Rust.

I think the best path for faux to solve this is to implement a better abstraction over:

when!(foo.method).then(|_| { mocked_return_object } )

When the closure is given, faux does not know that the parameter with a lifetime is not going to be mishandled, so it has to force the user to use unsafe or be unsound. However, the user knows, and they can tell `faux:

// made up syntax,I need to give this actual thought
when!(foo.method).return(mocked_return_object)

At that point, faux would know the user cannot be mishandling the references in the arguments because they have no access to them!

I have been away from faux lately due to there being a million other things in my head, but when I am back doing faux full force, this ergonomics issue is definitely in my top priority.

nrxus commented 3 years ago

Added new methods: c609864bded8b18809cf6c76d066a1db42b636c0 then_do and then_return that should solve the simple cases.

I am still unsure about the names but they will do for now. They should be up on the next release of faux, whenever that may be :grin:

nrxus commented 3 years ago

v0.0.6 added then_do and then_return to help handle some of the simple cases.