Repository: asomers/mockall (Rust)

Issue:
single-use lifetime lint warning on expanded automock
```rust
#[derive(Debug)]
pub struct MyEr;

#[mockall::automock]
pub trait MyTrait {
    /// # Errors
    ///
    /// some stuff
    fn get<'a>(
        &'a mut self,
        data: i32,
    ) -> Result<&'a str, MyEr>;
}
```

this code after cargo check produces 

```
warning: lifetime parameter `'a` only used once
  --> src/main.rs:13:12
   |
13 |     fn get<'a>(
   |            ^^
   |            |
   |            this lifetime...
   |            ...is used only here
   |
   = note: requested on the command line with `-W single-use-lifetimes`
help: elide the single-use lifetime
   |
13 -     fn get<'a>(
13 +     fn get<'_>(
   |
```

there is an easy way out by applying `#[allow]` on this method, but in my project allow is forbidden in favor of except (clippy::allow_attributes)



Discussion:
What Rustc compiler are you using?  Please do `rustc -Vv`.
```
rustc 1.83.0 (90b35a623 2024-11-26)
binary: rustc
commit-hash: 90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf
commit-date: 2024-11-26
host: x86_64-unknown-linux-gnu
release: 1.83.0
LLVM version: 19.1.1
```
This warning can be suppressed in the generated code. But I'm curious why the issue hasn't arisen already.  Is this an off-by-default warning that you enabled in your project?
Yes, this lint is allowed by default and set to warn in my project



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fe2f806..7e772787 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,14 @@
 All notable changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](http://semver.org/).
 
+## [ Unreleased ] - ReleaseDate
+
+### Fixed
+
+- Suppress `single-use-lifetimes` lints in the generated code, for cases where
+  the orginal code wouldn't have triggered the warning.
+  ([#627](https://github.com/asomers/mockall/pull/627))
+
 ## [ 0.13.1 ] - 2024-11-17
 
 ### Fixed
diff --git a/mockall_derive/src/mock_function.rs b/mockall_derive/src/mock_function.rs
index cc1b1040..27498b65 100644
--- a/mockall_derive/src/mock_function.rs
+++ b/mockall_derive/src/mock_function.rs
@@ -1222,6 +1222,7 @@ impl ToTokens for CommonExpectationsMethods<'_> {
                     Self(Vec::new())
                 }
             }
+            #[allow(single_use_lifetimes)]
             impl #ig Default for Expectations #tg #wc
             {
                 fn default() -> Self {
@@ -1806,6 +1807,7 @@ impl ToTokens for RefRfunc<'_> {
                 }
             }
 
+            #[allow(single_use_lifetimes)]
             impl #ig std::default::Default for Rfunc #tg #wc
             {
                 fn default() -> Self {
@@ -1896,6 +1898,7 @@ impl ToTokens for RefMutRfunc<'_> {
                 }
             }
 
+            #[allow(single_use_lifetimes)]
             impl #ig std::default::Default for Rfunc #tg #wc
             {
                 fn default() -> Self {
@@ -1984,6 +1987,7 @@ impl ToTokens for StaticRfunc<'_> {
                 }
             }
 
+            #[allow(single_use_lifetimes)]
             impl #ig std::default::Default for Rfunc #tg #wc
             {
                 fn default() -> Self {
@@ -2047,6 +2051,7 @@ impl ToTokens for RefExpectation<'_> {
 
                 #common_methods
             }
+            #[allow(single_use_lifetimes)]
             impl #ig Default for Expectation #tg #wc
             {
                 fn default() -> Self {
@@ -2135,6 +2140,7 @@ impl ToTokens for RefMutExpectation<'_> {
 
                 #common_methods
             }
+            #[allow(single_use_lifetimes)]
             impl #ig Default for Expectation #tg #wc
             {
                 fn default() -> Self {
@@ -2309,6 +2315,7 @@ impl ToTokens for StaticExpectation<'_> {
 
                 #common_methods
             }
+            #[allow(single_use_lifetimes)]
             impl #ig Default for Expectation #tg #wc
             {
                 fn default() -> Self {


Test patch:
diff --git a/mockall/tests/mock_life0.rs b/mockall/tests/mock_life0.rs
index 722f78e7..b9b7cb7b 100644
--- a/mockall/tests/mock_life0.rs
+++ b/mockall/tests/mock_life0.rs
@@ -2,6 +2,7 @@
 //! mock a method whose self parameter has an explicit lifetime
 //! https://github.com/asomers/mockall/issues/95
 #![deny(warnings)]
+#![allow(single_use_lifetimes)] // The lifetime is the whole point of this test
 
 use mockall::*;
 
diff --git a/mockall/tests/single-use-lifetime.rs b/mockall/tests/single-use-lifetime.rs
new file mode 100644
index 00000000..769b4d82
--- /dev/null
+++ b/mockall/tests/single-use-lifetime.rs
@@ -0,0 +1,22 @@
+// vim: tw=80
+//! Mock a function with a lifetime parameter that isn't single-use, but becomes
+//! single-use in the generated code.
+#![deny(warnings)]
+#![deny(single_use_lifetimes)]
+
+use mockall::*;
+
+#[automock]
+pub trait MyTrait {
+    #[allow(clippy::needless_lifetimes)]
+    fn get<'a>(&'a mut self, data: i32) -> std::io::Result<&'a str>;
+}
+
+#[test]
+fn returning() {
+    let mut mock = MockMyTrait::new();
+    mock.expect_get()
+        .returning(|_data| Err(std::io::Error::from_raw_os_error(42)));
+
+    mock.get(0x1a7ebabe).unwrap_err();
+}