diff --git a/.cirrus.yml b/.cirrus.yml index 87d843ad..cc9fe4f8 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -14,7 +14,7 @@ common: &COMMON task: name: MSRV container: - image: rust:1.70.0 + image: rust:1.71.0 cargo_lock_script: - cp Cargo.lock.msrv Cargo.lock << : *COMMON diff --git a/CHANGELOG.md b/CHANGELOG.md index 26e46842..eacc3b54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,13 +13,19 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Changed -- Raised MSRV to 1.70.0 to remove `lazy_static` dependency - ([#550](https://github.com/asomers/mockall/pull/550)) +- Raised MSRV to 1.71.0 due to the `C-unwind` ABI. + ([#585](https://github.com/asomers/mockall/pull/585)) - No longer poison a Context object's internal `Mutex` when panicing. This requires the "nightly" feature. ([#527](https://github.com/asomers/mockall/pull/527)) +### Fixed + +- Fixed panicing within mocked `extern "C"` functions, for example due to + unsatisfied expectations, with Rust 1.81.0 or newer. + ([#585](https://github.com/asomers/mockall/pull/585)) + ## [ 0.12.1 ] - 2023-12-21 ### Fixed diff --git a/README.md b/README.md index 6dbace06..dfc12898 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.70.0 and higher. Mockall's MSRV will not be +Mockall is supported on Rust 1.71.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 fbed4983..7e58e825 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.70" +rust-version = "1.71" description = """ A powerful mock object library for Rust. """ diff --git a/mockall/tests/automock_foreign_c.rs b/mockall/tests/automock_foreign_c.rs index 07eb47da..864bc77f 100644 --- a/mockall/tests/automock_foreign_c.rs +++ b/mockall/tests/automock_foreign_c.rs @@ -47,6 +47,6 @@ fn c_abi() { let _m = FOO_MTX.lock(); let ctx = mock_ffi::foo_context(); ctx.expect().returning(i64::from); - let p: unsafe extern "C" fn(u32) -> i64 = mock_ffi::foo; + let p: unsafe extern "C-unwind" fn(u32) -> i64 = mock_ffi::foo; assert_eq!(42, unsafe{p(42)}); } diff --git a/mockall/tests/automock_foreign_c_variadic.rs b/mockall/tests/automock_foreign_c_variadic.rs index 71a62ed5..5b6e4c26 100644 --- a/mockall/tests/automock_foreign_c_variadic.rs +++ b/mockall/tests/automock_foreign_c_variadic.rs @@ -13,11 +13,24 @@ pub mod ffi { } } +#[cfg(feature = "nightly")] +static FOO_MTX: std::sync::Mutex<()> = std::sync::Mutex::new(()); + #[test] #[cfg(feature = "nightly")] #[cfg_attr(miri, ignore)] fn mocked_c_variadic() { + let _m = FOO_MTX.lock(); let ctx = mock_ffi::foo_context(); ctx.expect().returning(|x, y| x * y); assert_eq!(6, unsafe{mock_ffi::foo(2, 3, 1, 4, 1)}); } + +#[test] +#[cfg(feature = "nightly")] +#[cfg_attr(miri, ignore)] +#[ignore = "https://github.com/rust-lang/rust/issues/126836"] +fn panics() { + let _m = FOO_MTX.lock(); + unsafe{ mock_ffi::foo(1,2,3) }; +} diff --git a/mockall_derive/src/mock_item.rs b/mockall_derive/src/mock_item.rs index bcbe70fb..daf8ac5a 100644 --- a/mockall_derive/src/mock_item.rs +++ b/mockall_derive/src/mock_item.rs @@ -95,7 +95,28 @@ impl From for MockItemModule { // Set the ABI to match the ForeignMod's ABI // for proper function linkage with external code. - f.sig.abi = Some(ifm.abi.clone()); + // + // BUT, use C-unwind instead of C, so we can panic + // from the mock function (rust-lang/rust #74990) + // + // BUT, don't use C-unwind for variadic functions, + // because it doesn't work yet (rust-lang/rust + // #126836) + let needs_c_unwind = if let Some(n) = &ifm.abi.name + { + n.value() == "C" && f.sig.variadic.is_none() + } else { + false + }; + f.sig.abi = Some(if needs_c_unwind { + Abi { + extern_token:ifm.abi.extern_token, + name: Some(LitStr::new("C-unwind", + ifm.abi.name.span())) + } + } else { + ifm.abi.clone() + }); let mf = mock_function::Builder::new(&f.sig, &f.vis) .attrs(&f.attrs)