From d829163143559aa8461e6f76685638f214dcabef Mon Sep 17 00:00:00 2001 From: Lukasz Anforowicz Date: Fri, 7 Jul 2023 11:33:51 -0700 Subject: [PATCH] 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 --- cc_bindings_from_rs/bindings.rs | 6 +++++ cc_bindings_from_rs/cc_bindings_from_rs.rs | 1 + cc_bindings_from_rs/test/structs/structs.rs | 30 +++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/cc_bindings_from_rs/bindings.rs b/cc_bindings_from_rs/bindings.rs index e4f7ec09..75965374 100644 --- a/cc_bindings_from_rs/bindings.rs +++ b/cc_bindings_from_rs/bindings.rs @@ -101,6 +101,12 @@ pub fn generate_bindings(input: &Input) -> Result { // 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 cf4e897e..79f68492 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 @@ inline void public_function() { // 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 c373d4d5..b253ab1a 100644 --- a/cc_bindings_from_rs/test/structs/structs.rs +++ b/cc_bindings_from_rs/test/structs/structs.rs @@ -259,3 +259,33 @@ pub mod nested_ptr_type_mutability_qualifiers { } } } + +/// 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 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, + } +}