Fix `offset_of` assertions for fields of types with interior mutability.
Implementation of `memoffset::offset_of` (from the `memoffset` crate)
ends up taking a reference to a struct. In `const` contexts (such as
the context of the assertion) this runs into
https://github.com/rust-lang/rust/issues/80384. This CL works around
this by opting the generated code into
`#![feature(const_refs_to_cell)]`.
After this CL bindings generated by `cc_bindings_from_rs` will require
a "nightly" version of the Rust compiler. This is unfortunate, but
this dependency already exists on `rs_bindings_from_cc` side (e.g.
requiring `impl_trait_in_assoc_type` and/or `type_alias_impl_trait`
unstable features).
This CL unblocks implementing `Drop` support. `Drop` support adds
bindings for additional types, some of which run into this bug.
PiperOrigin-RevId: 546337289
Change-Id: I1684b30a1ac096cc5115aabbe6e5c6504286947c
diff --git a/cc_bindings_from_rs/bindings.rs b/cc_bindings_from_rs/bindings.rs
index e4f7ec0..7596537 100644
--- a/cc_bindings_from_rs/bindings.rs
+++ b/cc_bindings_from_rs/bindings.rs
@@ -101,6 +101,12 @@
// bindings need to relax the `improper_ctypes_definitions` warning
// for `char` (and possibly for other built-in types in the future).
#![allow(improper_ctypes_definitions)] __NEWLINE__
+
+ // Workaround for b/290271595
+ //
+ // TODO(https://github.com/rust-lang/rust/issues/80384): Remove once the feature is
+ // stabilized.
+ #![feature(const_refs_to_cell)] __NEWLINE__
__NEWLINE__
#rs_body
diff --git a/cc_bindings_from_rs/cc_bindings_from_rs.rs b/cc_bindings_from_rs/cc_bindings_from_rs.rs
index cf4e897..79f6849 100644
--- a/cc_bindings_from_rs/cc_bindings_from_rs.rs
+++ b/cc_bindings_from_rs/cc_bindings_from_rs.rs
@@ -362,6 +362,7 @@
// test_crate
#![allow(improper_ctypes_definitions)]
+#![feature(const_refs_to_cell)]
#[no_mangle]
extern "C" fn __crubit_thunk__ANY_IDENTIFIER_CHARACTERS()
diff --git a/cc_bindings_from_rs/test/structs/structs.rs b/cc_bindings_from_rs/test/structs/structs.rs
index c373d4d..b253ab1 100644
--- a/cc_bindings_from_rs/test/structs/structs.rs
+++ b/cc_bindings_from_rs/test/structs/structs.rs
@@ -259,3 +259,33 @@
}
}
}
+
+/// This is a regression test for b/290271595 - it verifies that Rust-side
+/// `offset_of` assertions compile okay for bindings of types that use interior
+/// mutability. Before the bug was fixed, the test below would result in:
+///
+/// ```
+/// error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
+/// --> .../cc_bindings_from_rs/test/structs/structs_cc_api_impl.rs:254:23
+/// |
+/// 254 | const _: () = assert!(memoffset::offset_of!(::structs::...::SomeStruct, field) == 0);
+/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+/// |
+/// = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more
+/// information
+/// = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
+/// = note: this error originates in the macro `_memoffset__let_base_ptr` which comes from the
+/// expansion of the macro `memoffset::offset_of` (in Nightly builds, run with -Z
+/// macro-backtrace for more info)
+/// ```
+pub mod interior_mutability {
+ use std::cell::UnsafeCell;
+
+ #[derive(Debug, Default)]
+ pub struct SomeStruct {
+ /// `pub` to make sure that `assert!(memoffset::offset_of!(...) == ...)`
+ /// is generated. (Such assertions are skipped for private
+ /// fields.)
+ pub field: UnsafeCell<i32>,
+ }
+}