Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with mocking a trait which uses &Self #561

Closed
avysk opened this issue Mar 17, 2024 · 1 comment
Closed

Problem with mocking a trait which uses &Self #561

avysk opened this issue Mar 17, 2024 · 1 comment

Comments

@avysk
Copy link

avysk commented Mar 17, 2024

Hello,

I have the following problem. I wonder what I am doing incorrectly. Here is the working code:

trait Foo {
    fn foo(&self) -> Option<&Self>;
}

impl Foo for str {
    fn foo(&self) -> Option<&Self> {
        if self.is_empty() {
            None
        } else {
            Some(&self[1..])
        }
    }
}

fn main() {
    println!("{:?} {:?}", "".foo(), "bar".foo());
}

This can be run and it prints, of course, None Some("ar"). Now I add in the beginning some lines:

use mockall::automock;

#[automock]

with the intention to make trait Foo mockable. However, the thing explodes:

❯ cargo build                                                                                                                                  Compiling predicates-core v1.0.6                                                                                                            Compiling cfg-if v1.0.0
   Compiling termtree v0.4.1
   Compiling anstyle v1.0.6
   Compiling fragile v2.0.0                                                                                                                    Compiling downcast v0.11.0
   Compiling lazy_static v1.4.0
   Compiling mockall_derive v0.12.1
   Compiling predicates-tree v1.0.9
   Compiling predicates v3.1.0
   Compiling mockall v0.12.1
   Compiling mocking v0.1.0 (/tmp/mocking)
error[E0106]: missing lifetime specifier
 --> src/main.rs:4:7
  |
4 | trait Foo {                                                                                                                               |       ^ 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
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
  |
4 | trait F'static oo {
  |        +++++++
help: instead, you are more likely to want to return an owned value
  |
4 - trait Foo {
4 + trait oo {
  |

error[E0106]: missing lifetime specifier
 --> src/main.rs:4:7
  |
4 | trait Foo {
  |       ^ 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
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
  |
4 | trait F'static oo {
  |        +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
  |
3 | &#[automock]
  | +
help: ...or alternatively, you might want to return an owned value
  |
3 | #[automock]
  |

Some errors have detailed explanations: E0106, E0637.
For more information about an error, try `rustc --explain E0106`.
error: could not compile `mocking` (bin "mocking") due to 3 previous errors

Removing &Self usage from the trait helps. The following compiles and works:

use mockall::automock;

#[automock]
trait Foo {
    fn foo(&self) -> usize;
}

impl Foo for str {
    fn foo(&self) -> usize {
        self.len()
    }
}

fn main() {
    println!("{:?} {:?}", "".foo(), "bar".foo());
}

Just in case my Cargo.toml:

[package]
name = "mocking"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
mockall = "0.12.1"

What am I doing incorrectly?

@asomers
Copy link
Owner

asomers commented Mar 17, 2024

What am I doing incorrectly?

Nothing. This is a limitation of Rust and its lifetime system. Basically, Mockall needs for a mocked method's return value to be 'static. There are a few exceptions, for things like returning a reference. But supporting additional patterns like Option<&T> would require special code for every possible pattern.

I'm going to close this bug as a duplicate of #387 . You can see a workaround there.

@asomers asomers closed this as completed Mar 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants