mockall icon indicating copy to clipboard operation
mockall copied to clipboard

Support `Self` in function pointer arguments

Open TimeToogo opened this issue 2 years ago • 1 comments

Sample code:

#[cfg(test)]
use mockall::{automock, mock, predicate::*};

#[cfg_attr(test, automock)]
pub trait Example : Sized {
    fn register_callback<F: Fn(Self) + 'static>(&self, cb: F);
}

Produces 16 errors:

   Compiling mockall-repro v0.1.0 (/Users/elliotlevin/tmp/mockall-repro)
warning: unused import: `mock`
 --> src/lib.rs:2:25
  |
2 | use mockall::{automock, mock, predicate::*};
  |                         ^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0308]: mismatched types
 --> src/lib.rs:6:56
  |
4 | #[cfg_attr(test, automock)]
  |                  -------- arguments to this function are incorrect
5 | pub trait Example : Sized{
6 |     fn register_callback<F: Fn(Self) + 'static>(&self, cb: F);
  |                                                        ^^ expected enum `Matcher`, found struct `Common`
  |
  = note: expected reference `&Box<(dyn Fn(Matcher) + 'static)>`
             found reference `&Box<(dyn Fn(Common) + 'static)>`
note: associated function defined here
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `MockallMatcher0: Predicate<Box<(dyn Fn(Matcher) + 'static)>>` is not satisfied
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ the trait `Predicate<Box<(dyn Fn(Matcher) + 'static)>>` is not implemented for `MockallMatcher0`
  |
  = note: required for the cast from `MockallMatcher0` to the object type `dyn Predicate<Box<(dyn Fn(Matcher) + 'static)>> + Send`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `MockallMatcher0`
  |
4 | #[cfg_attr(test, automock mockall::Predicate<std::boxed::Box<(dyn std::ops::Fn(__mock_MockExample_Example::__register_callback::Matcher) + 'static)>>)]
  |                           +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

error[E0277]: expected a `Fn<(&Box<(dyn Fn(Matcher) + 'static)>,)>` closure, found `MockallF`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ expected an `Fn<(&Box<(dyn Fn(Matcher) + 'static)>,)>` closure, found `MockallF`
  |
  = note: expected a closure with arguments `(&Box<(dyn Fn(Common) + 'static)>,)`
             found a closure with arguments `(&Box<(dyn Fn(Matcher) + 'static)>,)`
  = note: required for the cast from `MockallF` to the object type `dyn for<'a> Fn(&'a Box<(dyn Fn(Matcher) + 'static)>) -> bool + Send`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: expected a `Fn<(&Box<(dyn Fn(Matcher) + 'static)>,)>` closure, found `MockallF`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ expected an `Fn<(&Box<(dyn Fn(Matcher) + 'static)>,)>` closure, found `MockallF`
  |
  = note: expected a closure with arguments `(&Box<(dyn Fn(Common) + 'static)>,)`
             found a closure with arguments `(&Box<(dyn Fn(Matcher) + 'static)>,)`
  = note: required for the cast from `MockallF` to the object type `dyn for<'a> Fn(&'a Box<(dyn Fn(Matcher) + 'static)>) -> bool`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
 --> src/lib.rs:6:56
  |
4 | #[cfg_attr(test, automock)]
  |                  -------- arguments to this function are incorrect
5 | pub trait Example : Sized{
6 |     fn register_callback<F: Fn(Self) + 'static>(&self, cb: F);
  |                                                        ^^ expected enum `Rfunc`, found struct `Expectation`
  |
  = note: expected struct `Box<(dyn Fn(Rfunc) + 'static)>`
             found struct `Box<(dyn Fn(Expectation) + 'static)>`
note: associated function defined here
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: expected a `FnOnce<(Box<(dyn Fn(Rfunc) + 'static)>,)>` closure, found `MockallF`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ expected an `FnOnce<(Box<(dyn Fn(Rfunc) + 'static)>,)>` closure, found `MockallF`
  |
  = note: expected a closure with arguments `(Box<(dyn Fn(Expectation) + 'static)>,)`
             found a closure with arguments `(Box<(dyn Fn(Rfunc) + 'static)>,)`
  = note: required for the cast from `MockallF` to the object type `dyn FnOnce(Box<(dyn Fn(Rfunc) + 'static)>) + Send`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: expected a `FnOnce<(Box<(dyn Fn(Rfunc) + 'static)>,)>` closure, found `MockallF`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ expected an `FnOnce<(Box<(dyn Fn(Rfunc) + 'static)>,)>` closure, found `MockallF`
  |
  = note: expected a closure with arguments `(Box<(dyn Fn(Expectation) + 'static)>,)`
             found a closure with arguments `(Box<(dyn Fn(Rfunc) + 'static)>,)`
  = note: required for the cast from `MockallF` to the object type `dyn FnOnce(Box<(dyn Fn(Rfunc) + 'static)>)`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: expected a `FnMut<(Box<(dyn Fn(Rfunc) + 'static)>,)>` closure, found `MockallF`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ expected an `FnMut<(Box<(dyn Fn(Rfunc) + 'static)>,)>` closure, found `MockallF`
  |
  = note: expected a closure with arguments `(Box<(dyn Fn(Expectation) + 'static)>,)`
             found a closure with arguments `(Box<(dyn Fn(Rfunc) + 'static)>,)`
  = note: required for the cast from `MockallF` to the object type `dyn FnMut(Box<(dyn Fn(Rfunc) + 'static)>) + Send`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: expected a `FnMut<(Box<(dyn Fn(Rfunc) + 'static)>,)>` closure, found `MockallF`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ expected an `FnMut<(Box<(dyn Fn(Rfunc) + 'static)>,)>` closure, found `MockallF`
  |
  = note: expected a closure with arguments `(Box<(dyn Fn(Expectation) + 'static)>,)`
             found a closure with arguments `(Box<(dyn Fn(Rfunc) + 'static)>,)`
  = note: required for the cast from `MockallF` to the object type `dyn FnMut(Box<(dyn Fn(Rfunc) + 'static)>)`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
 --> src/lib.rs:6:56
  |
4 | #[cfg_attr(test, automock)]
  |                  -------- arguments to this function are incorrect
5 | pub trait Example : Sized{
6 |     fn register_callback<F: Fn(Self) + 'static>(&self, cb: F);
  |                                                        ^^ expected struct `Common`, found struct `Expectation`
  |
  = note: expected reference `&Box<(dyn Fn(Common) + 'static)>`
             found reference `&Box<(dyn Fn(Expectation) + 'static)>`
note: associated function defined here
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `MockallMatcher0: Predicate<Box<(dyn Fn(Common) + 'static)>>` is not satisfied
 --> src/lib.rs:6:56
  |
4 | #[cfg_attr(test, automock)]
  |                  -------- required by a bound introduced by this call
5 | pub trait Example : Sized{
6 |     fn register_callback<F: Fn(Self) + 'static>(&self, cb: F);
  |                                                        ^^ the trait `Predicate<Box<(dyn Fn(Common) + 'static)>>` is not implemented for `MockallMatcher0`
  |
note: required by a bound in `Common::with`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ required by this bound in `Common::with`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `MockallMatcher0`
  |
4 | #[cfg_attr(test, automock mockall::Predicate<std::boxed::Box<(dyn std::ops::Fn(__mock_MockExample_Example::__register_callback::Common) + 'static)>>)]
  |                           ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

error[E0277]: expected a `Fn<(&Box<(dyn Fn(Common) + 'static)>,)>` closure, found `MockallF`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ expected an `Fn<(&Box<(dyn Fn(Common) + 'static)>,)>` closure, found `MockallF`
  |
  = note: expected a closure with arguments `(&Box<(dyn Fn(Expectation) + 'static)>,)`
             found a closure with arguments `(&Box<(dyn Fn(Common) + 'static)>,)`
note: required by a bound in `Common::withf`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ required by this bound in `Common::withf`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: expected a `Fn<(&Box<(dyn Fn(Common) + 'static)>,)>` closure, found `MockallF`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ expected an `Fn<(&Box<(dyn Fn(Common) + 'static)>,)>` closure, found `MockallF`
  |
  = note: expected a closure with arguments `(&Box<(dyn Fn(Expectation) + 'static)>,)`
             found a closure with arguments `(&Box<(dyn Fn(Common) + 'static)>,)`
note: required by a bound in `Common::withf_st`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ required by this bound in `Common::withf_st`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^
  |                  |
  |                  expected struct `Expectation`, found struct `Expectations`
  |                  arguments to this function are incorrect
  |
  = note: expected reference `&Box<(dyn Fn(Expectation) + 'static)>`
             found reference `&Box<(dyn Fn(Expectations) + 'static)>`
note: associated function defined here
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
 --> src/lib.rs:6:56
  |
4 | #[cfg_attr(test, automock)]
  |                  -------- arguments to this function are incorrect
5 | pub trait Example : Sized{
6 |     fn register_callback<F: Fn(Self) + 'static>(&self, cb: F);
  |                                                        ^^ expected struct `Expectation`, found struct `Expectations`
  |
  = note: expected struct `Box<(dyn Fn(Expectation) + 'static)>`
             found struct `Box<(dyn Fn(Expectations) + 'static)>`
note: associated function defined here
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: expected a `Fn<(Expectations,)>` closure, found `F`
 --> src/lib.rs:4:18
  |
4 | #[cfg_attr(test, automock)]
  |                  ^^^^^^^^ expected an `Fn<(Expectations,)>` closure, found `F`
  |
  = note: expected a closure with arguments `(MockExample,)`
             found a closure with arguments `(Expectations,)`
  = note: required for the cast from `F` to the object type `dyn Fn(Expectations)`
  = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
warning: `mockall-repro` (lib test) generated 1 warning
error: could not compile `mockall-repro` due to 16 previous errors; 1 warning emitted

This seems to apply the same for &Self, &mut Self, etc. I'm wondering if this is unsupported by mockall or a bug?

TimeToogo avatar Jan 17 '23 06:01 TimeToogo

Mockall doesn't support Self in that position. It could, with some extra work. But if you don't want to wait, here is a workaround:

use mockall::{automock, mock, predicate::*};

pub trait Example: Sized {
    fn register_callback<F: Fn(Self) + 'static>(&self, cb: F);
}

mock! {
    pub Example {}
    impl Example for Example {
        fn register_callback<F: Fn(MockExample) + 'static>(&self, cb: F);
    }
}

asomers avatar Jan 17 '23 18:01 asomers