asomers / mockall

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

Supporting mock with methods that return an object with a generic lifetime? #470

Closed Galgamins closed 1 year ago

Galgamins commented 1 year ago

Currently, you cannot use mockall to mock a method with a lifetime parameter where that lifetime is also part of the return type.

For example

pub struct MyStruct<'a>{
    test: &'a u8
}

impl<'a> MyStruct<'a>{
    pub fn create() -> MyStruct<'a>{
        MyStruct{
            test : &0
        }
    }
}

If you try to automock this you get an error use of undeclared lifetime name 'a

Is this something that can be supported in the future, or is this completely impossible to support?

asomers commented 1 year ago

It looks like you're trying to mock a constructor. The Expectation for a constructor must inherently be 'static, since it isn't associated with any mock object. That means that the returning closure can't capture any non-'static data. So the best you can do would be to use mock! instead of #[automock], and define the mock object's constructor to always return a static struct, like this:

mock! {
    pub struct MyStruct<'a> {
        pub fn create() -> MyStruct<'static>;
    }
}
Galgamins commented 1 year ago

Thanks for the suggestion!

When I do this

mock! {
    pub struct MyStruct<'a> {
        pub fn create() -> MyStruct<'static>;
    }
}

I get a compile error that highlights struct and says the compiler expected a identifier. Any idea what causes that?

asomers commented 1 year ago

No, not if you don't paste in the error.

Galgamins commented 1 year ago

test.rs

mock! {

    pub static struct MyStruct<'a> {

        pun fm create() -> MyStruct<'static>;

    }

}
error: expected identifier

  --> test.rs:16:9

   |

16 |     pub static struct MyStruct<'a> {

   |         ^^^^^^

 error: could not compile `test` due to previous error
asomers commented 1 year ago

Why did you put that static in between pub and struct? Are you forgetting that you aren't using C++ anymore?

Galgamins commented 1 year ago

Ah oops, yes I did. Though funny enough the same issue happens without the static.

mock! {

    pub struct MyStruct<'a> {

        pub fm create() -> MyStruct<'static>;

    }

}
error: expected identifier

  --> test.rs:16:9

   |

16 |     pub struct MyStruct<'a> {

   |         ^^^^^^

 error: could not compile `test` due to previous error
asomers commented 1 year ago

Now get rid of the "struct", like the error suggests.

Galgamins commented 1 year ago

Thanks, that solved the problem!