asomers / mockall

A powerful mock object library for Rust
Apache License 2.0
1.45k stars 61 forks source link

Can't apply `automock` to traits with default method implementions marked `#[inline]` #552

Closed tgnottingham closed 6 months ago

tgnottingham commented 6 months ago

The following code fails to compile:

#[mockall::automock]
trait Foo {
    #[inline]
    fn foo() -> i32 {
        1
    }
}

fn main() {}

With the error:

error[E0518]: attribute should be applied to function or closure
 --> src/main.rs:3:5
  |
1 | #[mockall::automock]
  | -------------------- not a function or closure
2 | trait Foo {
3 |     #[inline]
  |     ^^^^^^^^^

The issue is that the default method implementation is marked #[inline]. The same problem occurs for #[inline(always|never)].

mockall: 0.12.1 rustc: 1.76.0


I also checked #[cold] and #[must_use]. #[cold] causes a warning to be emitted that will become an error in the future:

warning: attribute should be applied to a function definition
 --> src/main.rs:3:5
  |
1 | #[mockall::automock]
  | -------------------- not a function definition
2 | trait Foo {
3 |     #[cold]
  |     ^^^^^^^
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: `#[warn(unused_attributes)]` on by default

#[must_use] causes a warning, but as of Rust 1.76.0, it's not scheduled to become a hard error (edit: oops, pasted in the wrong warning originally):

warning: `#[must_use]` has no effect when applied to a module
 --> src/main.rs:3:5
  |
3 |     #[must_use]
  |     ^^^^^^^^^^^
  |
  = note: `#[warn(unused_attributes)]` on by default

There may be other attributes that cause problems, but these were all I tested.

asomers commented 6 months ago

Thanks for reporting this. Supporting method attributes like that usually requires special handling within Mockall. It's pretty easy, but I have to do it for each and every one. These should be easy to add.