Repository: rust-lang/rust-bindgen
Pull request #2961 (2024-10-21 15:13:00)

Fix unsafe_op_in_unsafe_fn when using dynamic librarys and wrap_unsafe_ops
Closes https://github.com/rust-lang/rust-bindgen/issues/2957

WardBrian: r? @pvdrz
rustbot: **Error**: The feature `assign` is not enabled in this repository.
To enable it add its section in the `triagebot.toml` in the root of the repository.

Please file an issue on GitHub at [triagebot](https://github.com/rust-lang/triagebot) if there's a problem with this bot, or reach out on [#t-infra](https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra) on Zulip.

WardBrian: The failing test looks like it is just because some part of the CI config has gone stale, possibly due to github updates?
WardBrian: r? @emilio
rustbot: **Error**: The feature `assign` is not enabled in this repository.
To enable it add its section in the `triagebot.toml` in the root of the repository.

Please file an issue on GitHub at [triagebot](https://github.com/rust-lang/triagebot) if there's a problem with this bot, or reach out on [#t-infra](https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra) on Zulip.


Patch:
diff --git a/bindgen/codegen/dyngen.rs b/bindgen/codegen/dyngen.rs
index 4b2749ec..e75e11a2 100644
--- a/bindgen/codegen/dyngen.rs
+++ b/bindgen/codegen/dyngen.rs
@@ -83,6 +83,12 @@ impl DynamicItems {
         let init_fields = &self.init_fields;
         let struct_implementation = &self.struct_implementation;
 
+        let library_new = if ctx.options().wrap_unsafe_ops {
+            quote!(unsafe { ::libloading::Library::new(path) })
+        } else {
+            quote!(::libloading::Library::new(path))
+        };
+
         let from_library = if ctx.options().wrap_unsafe_ops {
             quote!(unsafe { Self::from_library(library) })
         } else {
@@ -100,7 +106,7 @@ impl DynamicItems {
                     path: P
                 ) -> Result<Self, ::libloading::Error>
                 where P: AsRef<::std::ffi::OsStr> {
-                    let library = ::libloading::Library::new(path)?;
+                    let library = #library_new?;
                     #from_library
                 }
 
@@ -202,6 +208,7 @@ impl DynamicItems {
         ident: Ident,
         ty: TokenStream,
         is_required: bool,
+        wrap_unsafe_ops: bool,
     ) {
         let member = if is_required {
             quote! { *mut #ty }
@@ -225,15 +232,20 @@ impl DynamicItems {
         });
 
         let ident_str = codegen::helpers::ast_ty::cstr_expr(ident.to_string());
-        self.constructor_inits.push(if is_required {
-            quote! {
-                let #ident = __library.get::<*mut #ty>(#ident_str).map(|sym| *sym)?;
-            }
+
+        let library_get = if wrap_unsafe_ops {
+            quote!(unsafe { __library.get::<*mut #ty>(#ident_str) })
         } else {
-            quote! {
-                let #ident = __library.get::<*mut #ty>(#ident_str).map(|sym| *sym);
-            }
-        });
+            quote!(__library.get::<*mut #ty>(#ident_str))
+        };
+
+        let qmark = if is_required { quote!(?) } else { quote!() };
+
+        let var_get = quote! {
+            let #ident = #library_get.map(|sym| *sym)#qmark;
+        };
+
+        self.constructor_inits.push(var_get);
 
         self.init_fields.push(quote! {
             #ident
diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs
index 2de56c19..ff6daac3 100644
--- a/bindgen/codegen/mod.rs
+++ b/bindgen/codegen/mod.rs
@@ -808,6 +808,7 @@ impl CodeGenerator for Var {
                         .to_rust_ty_or_opaque(ctx, &())
                         .into_token_stream(),
                     ctx.options().dynamic_link_require_all,
+                    ctx.options().wrap_unsafe_ops,
                 );
             } else {
                 result.push(tokens);


Test patch:
diff --git a/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_dynamic_loading_simple.rs b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_dynamic_loading_simple.rs
index 2f5b4cc5..05be5d99 100644
--- a/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_dynamic_loading_simple.rs
+++ b/bindgen-tests/tests/expectations/tests/wrap_unsafe_ops_dynamic_loading_simple.rs
@@ -16,13 +16,14 @@ pub struct TestLib {
         unsafe extern "C" fn() -> ::std::os::raw::c_int,
         ::libloading::Error,
     >,
+    pub FLUX: Result<*mut ::std::os::raw::c_int, ::libloading::Error>,
 }
 impl TestLib {
     pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
     where
         P: AsRef<::std::ffi::OsStr>,
     {
-        let library = ::libloading::Library::new(path)?;
+        let library = unsafe { ::libloading::Library::new(path) }?;
         unsafe { Self::from_library(library) }
     }
     pub unsafe fn from_library<L>(library: L) -> Result<Self, ::libloading::Error>
@@ -33,11 +34,14 @@ impl TestLib {
         let foo = unsafe { __library.get(b"foo\0") }.map(|sym| *sym);
         let bar = unsafe { __library.get(b"bar\0") }.map(|sym| *sym);
         let baz = unsafe { __library.get(b"baz\0") }.map(|sym| *sym);
+        let FLUX = unsafe { __library.get::<*mut ::std::os::raw::c_int>(b"FLUX\0") }
+            .map(|sym| *sym);
         Ok(TestLib {
             __library,
             foo,
             bar,
             baz,
+            FLUX,
         })
     }
     pub unsafe fn foo(
@@ -53,4 +57,7 @@ impl TestLib {
     pub unsafe fn baz(&self) -> ::std::os::raw::c_int {
         unsafe { (self.baz.as_ref().expect("Expected function, got error."))() }
     }
+    pub unsafe fn FLUX(&self) -> *mut ::std::os::raw::c_int {
+        *self.FLUX.as_ref().expect("Expected variable, got error.")
+    }
 }
diff --git a/bindgen-tests/tests/headers/wrap_unsafe_ops_dynamic_loading_simple.h b/bindgen-tests/tests/headers/wrap_unsafe_ops_dynamic_loading_simple.h
index 2b8c1071..36a638ae 100644
--- a/bindgen-tests/tests/headers/wrap_unsafe_ops_dynamic_loading_simple.h
+++ b/bindgen-tests/tests/headers/wrap_unsafe_ops_dynamic_loading_simple.h
@@ -3,3 +3,5 @@
 int foo(int x, int y);
 int bar(void *x);
 int baz();
+
+const int FLUX;