From 88f315f7dd8ef8c63bf3c19bd93d72170c1aea63 Mon Sep 17 00:00:00 2001 From: Expyron <5100376+Expyron@users.noreply.github.com> Date: Thu, 8 Feb 2024 09:35:38 +0100 Subject: [PATCH 1/2] Use `const Mutex::new()` whenever possible --- mockall/examples/synchronization.rs | 7 ++----- mockall/tests/automock_foreign_c.rs | 4 +--- mockall/tests/automock_generic_static_method.rs | 4 +--- mockall/tests/automock_module.rs | 4 +--- mockall/tests/automock_nonsend.rs | 8 +++----- ..._generic_struct_with_generic_static_method.rs | 4 +--- ...ock_static_method_with_lifetime_parameters.rs | 4 +--- mockall/tests/mock_struct_with_static_method.rs | 4 +--- mockall_derive/src/mock_function.rs | 16 +++++++--------- 9 files changed, 18 insertions(+), 37 deletions(-) diff --git a/mockall/examples/synchronization.rs b/mockall/examples/synchronization.rs index b12f844c..a943b881 100644 --- a/mockall/examples/synchronization.rs +++ b/mockall/examples/synchronization.rs @@ -6,7 +6,7 @@ //! overwrites the mock that another test is depending on. The solution to this //! is to add some form of synchronization so that tests that depend on a //! specific mock will not run in parallel. This is easily achieved using a -//! Mutex and the lazy_static crate. +//! Mutex. #![deny(warnings)] use mockall_double::double; @@ -34,12 +34,9 @@ fn main() { #[cfg(test)] mod test { use crate::my_mock::MockThing; - use lazy_static::lazy_static; use std::sync::Mutex; - lazy_static! { - static ref MTX: Mutex<()> = Mutex::new(()); - } + static MTX: Mutex<()> = Mutex::new(()); #[test] fn test_1() { diff --git a/mockall/tests/automock_foreign_c.rs b/mockall/tests/automock_foreign_c.rs index 4eaebf07..07eb47da 100644 --- a/mockall/tests/automock_foreign_c.rs +++ b/mockall/tests/automock_foreign_c.rs @@ -11,9 +11,7 @@ mod ffi { } } -lazy_static! { - static ref FOO_MTX: Mutex<()> = Mutex::new(()); -} +static FOO_MTX: Mutex<()> = Mutex::new(()); // Ensure we can still use the original mocked function pub fn normal_usage() { diff --git a/mockall/tests/automock_generic_static_method.rs b/mockall/tests/automock_generic_static_method.rs index 88adb8dc..3afc95e8 100644 --- a/mockall/tests/automock_generic_static_method.rs +++ b/mockall/tests/automock_generic_static_method.rs @@ -5,9 +5,7 @@ use mockall::*; use std::sync::Mutex; -lazy_static! { - static ref A_MTX: Mutex<()> = Mutex::new(()); -} +static A_MTX: Mutex<()> = Mutex::new(()); #[automock] trait A { diff --git a/mockall/tests/automock_module.rs b/mockall/tests/automock_module.rs index 8f6f6c39..ddfe53e1 100644 --- a/mockall/tests/automock_module.rs +++ b/mockall/tests/automock_module.rs @@ -8,9 +8,7 @@ pub mod m { use mockall::*; type T = u32; - lazy_static! { - static ref BAR_MTX: Mutex<()> = Mutex::new(()); - } + static BAR_MTX: Mutex<()> = Mutex::new(()); #[automock] pub mod foo { diff --git a/mockall/tests/automock_nonsend.rs b/mockall/tests/automock_nonsend.rs index 5c8382e4..059879f4 100644 --- a/mockall/tests/automock_nonsend.rs +++ b/mockall/tests/automock_nonsend.rs @@ -95,11 +95,9 @@ pub mod static_method { use super::*; use std::sync::Mutex; - lazy_static! { - static ref FOO_MTX: Mutex<()> = Mutex::new(()); - static ref BAR_MTX: Mutex<()> = Mutex::new(()); - static ref BAZ_MTX: Mutex<()> = Mutex::new(()); - } + static FOO_MTX: Mutex<()> = Mutex::new(()); + static BAR_MTX: Mutex<()> = Mutex::new(()); + static BAZ_MTX: Mutex<()> = Mutex::new(()); #[automock] trait Foo { diff --git a/mockall/tests/mock_generic_struct_with_generic_static_method.rs b/mockall/tests/mock_generic_struct_with_generic_static_method.rs index b01d38b2..1f93f3fa 100644 --- a/mockall/tests/mock_generic_struct_with_generic_static_method.rs +++ b/mockall/tests/mock_generic_struct_with_generic_static_method.rs @@ -11,9 +11,7 @@ mock! { } } -lazy_static! { - static ref FOO_MTX: Mutex<()> = Mutex::new(()); -} +static FOO_MTX: Mutex<()> = Mutex::new(()); // Checkpointing the mock object should not checkpoint static methods too #[test] diff --git a/mockall/tests/mock_static_method_with_lifetime_parameters.rs b/mockall/tests/mock_static_method_with_lifetime_parameters.rs index 3808ff0a..c71ece5c 100644 --- a/mockall/tests/mock_static_method_with_lifetime_parameters.rs +++ b/mockall/tests/mock_static_method_with_lifetime_parameters.rs @@ -20,9 +20,7 @@ mock!{ } } -lazy_static! { - static ref FOO_MTX: Mutex<()> = Mutex::new(()); -} +static FOO_MTX: Mutex<()> = Mutex::new(()); #[test] fn return_const() { diff --git a/mockall/tests/mock_struct_with_static_method.rs b/mockall/tests/mock_struct_with_static_method.rs index 98598964..ffaebd06 100644 --- a/mockall/tests/mock_struct_with_static_method.rs +++ b/mockall/tests/mock_struct_with_static_method.rs @@ -10,9 +10,7 @@ mock!{ } } -lazy_static! { - static ref BAR_MTX: Mutex<()> = Mutex::new(()); -} +static BAR_MTX: Mutex<()> = Mutex::new(()); // Checkpointing the mock object should not checkpoint static methods #[test] diff --git a/mockall_derive/src/mock_function.rs b/mockall_derive/src/mock_function.rs index 86e45e6d..31701cfb 100644 --- a/mockall_derive/src/mock_function.rs +++ b/mockall_derive/src/mock_function.rs @@ -1188,14 +1188,14 @@ impl<'a> ToTokens for CommonExpectationsMethods<'a> { &mut self.0[__mockall_l - 1] } - #v fn new() -> Self { - Self::default() + #v const fn new() -> Self { + Self(Vec::new()) } } impl #ig Default for Expectations #tg #wc { fn default() -> Self { - Expectations(Vec::new()) + Expectations::new() } } ).to_tokens(tokens); @@ -1397,12 +1397,10 @@ impl<'a> ToTokens for ConcreteExpectationGuard<'a> { let (ei_ig, _, _) = e_generics.split_for_impl(); let v = &self.f.privmod_vis; quote!( - ::mockall::lazy_static! { - #[doc(hidden)] - #v static ref EXPECTATIONS: - ::std::sync::Mutex = - ::std::sync::Mutex::new(Expectations::new()); - } + #[doc(hidden)] + #v static EXPECTATIONS: + ::std::sync::Mutex = + ::std::sync::Mutex::new(Expectations::new()); /// Like an [`&Expectation`](struct.Expectation.html) but /// protected by a Mutex guard. Useful for mocking static /// methods. Forwards accesses to an `Expectation` object. From 1f61dc092060c2ebafe7554b330c575662a558c7 Mon Sep 17 00:00:00 2001 From: Expyron <5100376+Expyron@users.noreply.github.com> Date: Thu, 8 Feb 2024 17:36:40 +0100 Subject: [PATCH 2/2] Raise MSRV to 1.70.0 to remove `lazy_static` dependency --- .cirrus.yml | 2 +- CHANGELOG.md | 6 ++++++ README.md | 2 +- mockall/Cargo.toml | 5 ++--- mockall/src/lib.rs | 4 ---- mockall_derive/src/mock_function.rs | 29 +++++++++++++++++------------ 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index c0077dea..87d843ad 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -14,7 +14,7 @@ common: &COMMON task: name: MSRV container: - image: rust:1.64.0 + image: rust:1.70.0 cargo_lock_script: - cp Cargo.lock.msrv Cargo.lock << : *COMMON diff --git a/CHANGELOG.md b/CHANGELOG.md index e34f75c4..83c4c636 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [ Unreleased ] - ReleaseDate + +### Changed + +- Raised MSRV to 1.70.0 to remove `lazy_static` dependency + ([#550](https://github.com/asomers/mockall/pull/550)) ## [ 0.12.1 ] - 2023-12-21 diff --git a/README.md b/README.md index 91d2039f..6dbace06 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ See the [API docs](https://docs.rs/mockall) for more information. # Minimum Supported Rust Version (MSRV) -Mockall is supported on Rust 1.64.0 and higher. Mockall's MSRV will not be +Mockall is supported on Rust 1.70.0 and higher. Mockall's MSRV will not be changed in the future without bumping the major or minor version. # License diff --git a/mockall/Cargo.toml b/mockall/Cargo.toml index a55fd883..3ce41c48 100644 --- a/mockall/Cargo.toml +++ b/mockall/Cargo.toml @@ -9,7 +9,7 @@ categories = ["development-tools::testing"] keywords = ["mock", "mocking", "testing"] documentation = "https://docs.rs/mockall" edition = "2021" -rust-version = "1.60" +rust-version = "1.70" description = """ A powerful mock object library for Rust. """ @@ -41,7 +41,6 @@ nightly = [ cfg-if = "1.0" downcast = "0.11" fragile = "2.0" -lazy_static = "1.1" predicates = { version = "3.0.0", default-features = false } predicates-tree = "1.0" mockall_derive = { version = "=0.12.1", path = "../mockall_derive" } @@ -53,7 +52,7 @@ mockall_double = { version = "^0.3.1", path = "../mockall_double" } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -tracing = "0.1.32" +tracing = "0.1.35" [[example]] name = "serde" diff --git a/mockall/src/lib.rs b/mockall/src/lib.rs index a45d90a8..9333fe3d 100644 --- a/mockall/src/lib.rs +++ b/mockall/src/lib.rs @@ -1162,10 +1162,6 @@ pub use downcast::{Any, Downcast}; #[doc(hidden)] pub use fragile::Fragile; -/// For mocking static methods -#[doc(hidden)] -pub use lazy_static::lazy_static; - pub use predicates::{ boolean::PredicateBooleanExt, prelude::{ diff --git a/mockall_derive/src/mock_function.rs b/mockall_derive/src/mock_function.rs index 31701cfb..6b898ed8 100644 --- a/mockall_derive/src/mock_function.rs +++ b/mockall_derive/src/mock_function.rs @@ -518,7 +518,7 @@ impl MockFunction { use ::mockall::{ViaDebug, ViaNothing}; let no_match_msg = #no_match_msg; #deref { - let __mockall_guard = #outer_mod_path::EXPECTATIONS + let __mockall_guard = #outer_mod_path::get_expectations() .lock().unwrap(); /* * TODO: catch panics, then gracefully release the mutex @@ -558,7 +558,7 @@ impl MockFunction { quote!( #(#attrs)* { - let __mockall_timeses = #inner_mod_ident::EXPECTATIONS.lock() + let __mockall_timeses = #inner_mod_ident::get_expectations().lock() .unwrap() .checkpoint() .collect::>(); @@ -1398,9 +1398,13 @@ impl<'a> ToTokens for ConcreteExpectationGuard<'a> { let v = &self.f.privmod_vis; quote!( #[doc(hidden)] - #v static EXPECTATIONS: - ::std::sync::Mutex = - ::std::sync::Mutex::new(Expectations::new()); + #v fn get_expectations() -> &'static ::std::sync::Mutex { + static EXPECTATIONS: + ::std::sync::Mutex = + ::std::sync::Mutex::new(Expectations::new()); + &EXPECTATIONS + } + /// Like an [`&Expectation`](struct.Expectation.html) but /// protected by a Mutex guard. Useful for mocking static /// methods. Forwards accesses to an `Expectation` object. @@ -1464,11 +1468,12 @@ impl<'a> ToTokens for GenericExpectationGuard<'a> { let tbf = tg.as_turbofish(); let v = &self.f.privmod_vis; quote!( - ::mockall::lazy_static! { - #v static ref EXPECTATIONS: - ::std::sync::Mutex = - ::std::sync::Mutex::new(GenericExpectations::new()); + #[doc(hidden)] + #v fn get_expectations() -> &'static ::std::sync::Mutex { + static CELL: ::std::sync::OnceLock<::std::sync::Mutex> = ::std::sync::OnceLock::new(); + CELL.get_or_init(|| ::std::sync::Mutex::new(GenericExpectations::new())) } + /// Like an [`&Expectation`](struct.Expectation.html) but /// protected by a Mutex guard. Useful for mocking static /// methods. Forwards accesses to an `Expectation` object. @@ -1569,7 +1574,7 @@ impl<'a> ToTokens for Context<'a> { } #[doc(hidden)] #v fn do_checkpoint() { - let __mockall_timeses = EXPECTATIONS + let __mockall_timeses = get_expectations() .lock() .unwrap() .checkpoint() @@ -1581,7 +1586,7 @@ impl<'a> ToTokens for Context<'a> { #v fn expect #meth_ig ( &self,) -> ExpectationGuard #e_tg #meth_wc { - ExpectationGuard::new(EXPECTATIONS.lock().unwrap()) + ExpectationGuard::new(get_expectations().lock().unwrap()) } } impl #ty_ig Default for Context #ty_tg #ty_wc { @@ -1595,7 +1600,7 @@ impl<'a> ToTokens for Context<'a> { // Drain all expectations so other tests can run with a // blank slate. But ignore errors so we don't // double-panic. - let _ = EXPECTATIONS + let _ = get_expectations() .lock() .map(|mut g| g.checkpoint().collect::>()); } else {