From 86e8c0c68a9cea9733ce9f8134d53611896cfa48 Mon Sep 17 00:00:00 2001 From: Lukasz Anforowicz Date: Mon, 16 Dec 2024 23:51:04 +0000 Subject: [PATCH] Suppress `unused_unsafe` warnings within the generated code. Sometimes Rust functions declared inside the `#[cxx::bridge]` have to be marked as unsafe (e.g. if they need to use an explicit lifetime). When the actual, wrapped function is _not_ unsafe, then the generated code will result in an `unused_unsafe` warning. For example: ``` Compiling cxx-test-suite v0.0.0 (/usr/local/google/home/lukasza/src/github/cxx/tests/ffi) error: unnecessary `unsafe` block --> tests/ffi/lib.rs:276:19 | 276 | unsafe fn r_return_str_via_out_param<'a>(shared: &'a Shared, out_param: &mut &'a str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here --> tests/ffi/lib.rs:20:9 | 20 | #![deny(warnings)] // Check that expansion of `cxx::bridge` doesn't trigger warnings. | ^^^^^^^^ = note: `#[deny(unused_unsafe)]` implied by `#[deny(warnings)]` ``` The warning above comes from the following expansion: ``` unsafe fn __r_return_str_via_out_param<'a>(...) { // The `unsafe` block below is unnecessary if the actual, wrapped // function is *not* `unsafe`. unsafe { super::r_return_str_via_out_param(...) } } ``` This commit avoids the warning by including an explicit `#[allow(unused_unsafe)]` in the generated code. --- macro/src/expand.rs | 5 ++++- tests/ffi/lib.rs | 7 +++++++ tests/ffi/module.rs | 2 ++ tests/ffi/tests.cc | 6 ++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/macro/src/expand.rs b/macro/src/expand.rs index 8256db1b8..35597f0f1 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -1231,11 +1231,14 @@ fn expand_rust_function_shim_super( }; let mut body = quote_spanned!(span=> #call(#(#vars,)*)); + let mut allow_unused_unsafe = quote!(); if unsafety.is_some() { - body = quote_spanned!(span=> unsafe { #body }); + body = quote_spanned!(span=>unsafe { #body }); + allow_unused_unsafe = quote_spanned!(span=> #[allow(unused_unsafe)]); } quote_spanned! {span=> + #allow_unused_unsafe #unsafety fn #local_name #generics(#(#all_args,)*) #ret { #body } diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs index 57d94ee76..d15a48b5d 100644 --- a/tests/ffi/lib.rs +++ b/tests/ffi/lib.rs @@ -17,6 +17,7 @@ #![allow(unknown_lints)] #![warn(rust_2024_compatibility)] #![forbid(unsafe_op_in_unsafe_fn)] +#![deny(warnings)] // Check that expansion of `cxx::bridge` doesn't trigger warnings. pub mod cast; pub mod module; @@ -272,6 +273,7 @@ pub mod ffi { fn r_return_ref(shared: &Shared) -> &usize; fn r_return_mut(shared: &mut Shared) -> &mut usize; fn r_return_str(shared: &Shared) -> &str; + unsafe fn r_return_str_via_out_param<'a>(shared: &'a Shared, out_param: &mut &'a str); fn r_return_sliceu8(shared: &Shared) -> &[u8]; fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8]; fn r_return_rust_string() -> String; @@ -491,6 +493,11 @@ fn r_return_str(shared: &ffi::Shared) -> &str { "2020" } +fn r_return_str_via_out_param<'a>(shared: &'a ffi::Shared, out_param: &mut &'a str) { + let _ = shared; + *out_param = "2020" +} + fn r_return_sliceu8(shared: &ffi::Shared) -> &[u8] { let _ = shared; b"2020" diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs index 21a86206d..e298c0250 100644 --- a/tests/ffi/module.rs +++ b/tests/ffi/module.rs @@ -1,3 +1,5 @@ +#![deny(warnings)] // Check that expansion of `cxx::bridge` doesn't trigger warnings. + #[cxx::bridge(namespace = "tests")] pub mod ffi { struct Job { diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index ca71276f8..2292914cd 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -866,6 +866,12 @@ extern "C" const char *cxx_run_test() noexcept { cstring.reserve(5); ASSERT(cstring.capacity() >= 5); + { + rust::Str out_param; + r_return_str_via_out_param(Shared{2020}, out_param); + ASSERT(out_param == "2020"); + } + rust::Str cstr = "test"; rust::Str other_cstr = "foo"; swap(cstr, other_cstr);