Generate bindings for inline namespaces
In the bindings, we use fully qualified identifiers everywhere.
In the following example, `C` will always be referred to in the bindings as `A::B::C` regardless of whether the C++ equivalent was `A::B::C`, `A::C` or `C`.
```
namespace A {
inline namespace B {
struct C{};
} // B
} // A
```
So, we don't need any special logic for inline namespaces.
PiperOrigin-RevId: 453906326
diff --git a/rs_bindings_from_cc/importers/namespace.cc b/rs_bindings_from_cc/importers/namespace.cc
index 33903a5..130fa6c 100644
--- a/rs_bindings_from_cc/importers/namespace.cc
+++ b/rs_bindings_from_cc/importers/namespace.cc
@@ -19,10 +19,6 @@
"Namespaces are not supported yet");
}
- if (namespace_decl->isInline()) {
- return ictx_.ImportUnsupportedItem(
- namespace_decl, "Inline namespaces are not supported yet");
- }
if (namespace_decl->isAnonymousNamespace()) {
return ictx_.ImportUnsupportedItem(
namespace_decl, "Anonymous namespaces are not supported yet");
diff --git a/rs_bindings_from_cc/ir_from_cc_test.rs b/rs_bindings_from_cc/ir_from_cc_test.rs
index a49f6b1..df7d35d 100644
--- a/rs_bindings_from_cc/ir_from_cc_test.rs
+++ b/rs_bindings_from_cc/ir_from_cc_test.rs
@@ -3239,3 +3239,29 @@
let ir = ir_from_cc("struct MyStruct { virtual void run() = 0; };").unwrap();
assert_ir_matches!(ir, quote! { UnsupportedItem { name: "MyStruct" ... } });
}
+
+#[test]
+fn test_inline_namespace() {
+ let ir = ir_from_cc(
+ r#"
+ namespace test_namespace_bindings {
+ inline namespace inner {
+ struct MyStruct {};
+ }
+ }"#,
+ )
+ .unwrap();
+
+ assert_ir_matches!(
+ ir,
+ quote! {
+ ...
+ Namespace(Namespace {
+ name: "test_namespace_bindings" ...
+ }) ...
+ Namespace(Namespace {
+ name: "inner" ...
+ }) ...
+ }
+ );
+}
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index 5012a50..85d6be4 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -5965,4 +5965,44 @@
);
Ok(())
}
+
+ #[test]
+ fn test_inline_namespace() -> Result<()> {
+ let rs_api = generate_bindings_tokens(&ir_from_cc(
+ r#"
+ namespace test_namespace_bindings {
+ inline namespace inner {
+ struct MyStruct {};
+ }
+ void processMyStruct(MyStruct s);
+ }
+ void processMyStructOutsideNamespace(test_namespace_bindings::inner::MyStruct s);
+ void processMyStructSkipInlineNamespaceQualifier(test_namespace_bindings::MyStruct s);
+ "#,
+ )?)?
+ .rs_api;
+
+ assert_rs_matches!(
+ rs_api,
+ quote! {
+ ...
+ pub mod test_namespace_bindings {
+ ...
+ pub mod inner {
+ ...
+ pub struct MyStruct {...} ...
+ }
+ ...
+ pub fn processMyStruct(s: crate::test_namespace_bindings::inner::MyStruct)
+ ...
+ }
+ ...
+ pub fn processMyStructOutsideNamespace(s: crate::test_namespace_bindings::inner::MyStruct)
+ ...
+ pub fn processMyStructSkipInlineNamespaceQualifier(s: crate::test_namespace_bindings::inner::MyStruct)
+ ...
+ }
+ );
+ Ok(())
+ }
}
diff --git a/rs_bindings_from_cc/test/golden/BUILD b/rs_bindings_from_cc/test/golden/BUILD
index 0404549..d269e01 100644
--- a/rs_bindings_from_cc/test/golden/BUILD
+++ b/rs_bindings_from_cc/test/golden/BUILD
@@ -19,6 +19,7 @@
[cc_library(
name = name + "_cc",
hdrs = [name + ".h"],
+ copts = ["-Wno-google3-inline-namespace"],
deps = [d + "_cc" for d in (DEPS[name] if name in DEPS else [])],
) for name in TESTS]
diff --git a/rs_bindings_from_cc/test/golden/namespace.h b/rs_bindings_from_cc/test/golden/namespace.h
index 0dccba4..9159fc7 100644
--- a/rs_bindings_from_cc/test/golden/namespace.h
+++ b/rs_bindings_from_cc/test/golden/namespace.h
@@ -39,4 +39,15 @@
} // namespace inner
} // namespace test_namespace_bindings_reopened
+namespace test_namespace_bindings_inline {
+inline namespace inner {
+struct StructInInlineNamespace {};
+} // namespace inner
+} // namespace test_namespace_bindings_inline
+
+void useStructInInlineNamespaceWithFullQualifier(
+ test_namespace_bindings_inline::inner::StructInInlineNamespace s);
+void useStructInInlineNamespaceSkipInlineQualifier(
+ test_namespace_bindings_inline::StructInInlineNamespace s);
+
#endif // THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_GOLDEN_NAMESPACE_H_
diff --git a/rs_bindings_from_cc/test/golden/namespace_rs_api.rs b/rs_bindings_from_cc/test/golden/namespace_rs_api.rs
index aac23e5..24be82f 100644
--- a/rs_bindings_from_cc/test/golden/namespace_rs_api.rs
+++ b/rs_bindings_from_cc/test/golden/namespace_rs_api.rs
@@ -300,6 +300,191 @@
// namespace test_namespace_bindings_reopened
+pub mod test_namespace_bindings_inline {
+ pub mod inner {
+ #[ctor::recursively_pinned]
+ #[repr(C)]
+ pub struct StructInInlineNamespace {
+ __non_field_data: [crate::rust_std::mem::MaybeUninit<u8>; 1],
+ }
+ forward_declare::unsafe_define!(
+ forward_declare::symbol!("StructInInlineNamespace"),
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace
+ );
+
+ impl ctor::CtorNew<()> for StructInInlineNamespace {
+ type CtorType = impl ctor::Ctor<Output = Self>;
+ #[inline(always)]
+ fn ctor_new(args: ()) -> Self::CtorType {
+ let () = args;
+ ctor::FnCtor::new(
+ move |dest: crate::rust_std::pin::Pin<
+ &mut crate::rust_std::mem::MaybeUninit<Self>,
+ >| {
+ unsafe {
+ crate::detail::__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceC1Ev(crate::rust_std::pin::Pin::into_inner_unchecked(dest));
+ }
+ },
+ )
+ }
+ }
+
+ impl<'b>
+ ctor::CtorNew<&'b crate::test_namespace_bindings_inline::inner::StructInInlineNamespace>
+ for StructInInlineNamespace
+ {
+ type CtorType = impl ctor::Ctor<Output = Self>;
+ #[inline(always)]
+ fn ctor_new(
+ args: &'b crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ ) -> Self::CtorType {
+ let __param_0 = args;
+ ctor::FnCtor::new(
+ move |dest: crate::rust_std::pin::Pin<
+ &mut crate::rust_std::mem::MaybeUninit<Self>,
+ >| {
+ unsafe {
+ crate::detail::__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceC1ERKS1_(crate::rust_std::pin::Pin::into_inner_unchecked(dest),__param_0);
+ }
+ },
+ )
+ }
+ }
+ impl<'b>
+ ctor::CtorNew<(
+ &'b crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ )> for StructInInlineNamespace
+ {
+ type CtorType = impl ctor::Ctor<Output = Self>;
+ #[inline(always)]
+ fn ctor_new(
+ args: (&'b crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,),
+ ) -> Self::CtorType {
+ let (arg,) = args;
+ <Self as ctor::CtorNew<
+ &'b crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >>::ctor_new(arg)
+ }
+ }
+
+ impl<'b>
+ ctor::CtorNew<
+ ctor::RvalueReference<
+ 'b,
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ > for StructInInlineNamespace
+ {
+ type CtorType = impl ctor::Ctor<Output = Self>;
+ #[inline(always)]
+ fn ctor_new(
+ args: ctor::RvalueReference<
+ 'b,
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ ) -> Self::CtorType {
+ let __param_0 = args;
+ ctor::FnCtor::new(
+ move |dest: crate::rust_std::pin::Pin<
+ &mut crate::rust_std::mem::MaybeUninit<Self>,
+ >| {
+ unsafe {
+ crate::detail::__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceC1EOS1_(crate::rust_std::pin::Pin::into_inner_unchecked(dest),__param_0);
+ }
+ },
+ )
+ }
+ }
+ impl<'b>
+ ctor::CtorNew<(
+ ctor::RvalueReference<
+ 'b,
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ )> for StructInInlineNamespace
+ {
+ type CtorType = impl ctor::Ctor<Output = Self>;
+ #[inline(always)]
+ fn ctor_new(
+ args: (
+ ctor::RvalueReference<
+ 'b,
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ ),
+ ) -> Self::CtorType {
+ let (arg,) = args;
+ <Self as ctor::CtorNew<
+ ctor::RvalueReference<
+ 'b,
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ >>::ctor_new(arg)
+ }
+ }
+
+ impl<'b>
+ ::ctor::Assign<
+ &'b crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ > for StructInInlineNamespace
+ {
+ #[inline(always)]
+ fn assign<'a>(
+ self: crate::rust_std::pin::Pin<&'a mut Self>,
+ __param_0:&'b crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ ) {
+ unsafe {
+ crate::detail::__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceaSERKS1_(self,__param_0);
+ }
+ }
+ }
+
+ impl<'b>
+ ::ctor::Assign<
+ ctor::RvalueReference<
+ 'b,
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ > for StructInInlineNamespace
+ {
+ #[inline(always)]
+ fn assign<'a>(
+ self: crate::rust_std::pin::Pin<&'a mut Self>,
+ __param_0: ctor::RvalueReference<
+ 'b,
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ ) {
+ unsafe {
+ crate::detail::__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceaSEOS1_(self,__param_0);
+ }
+ }
+ }
+ }
+
+ // namespace inner
+}
+
+// namespace test_namespace_bindings_inline
+
+#[inline(always)]
+pub fn useStructInInlineNamespaceWithFullQualifier(
+ s: crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+) {
+ unsafe {
+ crate::detail::__rust_thunk___Z43useStructInInlineNamespaceWithFullQualifierN30test_namespace_bindings_inline5inner23StructInInlineNamespaceE(s)
+ }
+}
+
+#[inline(always)]
+pub fn useStructInInlineNamespaceSkipInlineQualifier(
+ s: crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+) {
+ unsafe {
+ crate::detail::__rust_thunk___Z45useStructInInlineNamespaceSkipInlineQualifierN30test_namespace_bindings_inline5inner23StructInInlineNamespaceE(s)
+ }
+}
+
// THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_GOLDEN_NAMESPACE_H_
mod detail {
@@ -365,6 +550,67 @@
pub(crate) fn __rust_thunk___ZN32test_namespace_bindings_reopened5inner1zENS0_1SE(
s: crate::test_namespace_bindings_reopened::inner::S,
);
+ pub(crate) fn __rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceC1Ev<
+ 'a,
+ >(
+ __this: &'a mut crate::rust_std::mem::MaybeUninit<
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ );
+ pub(crate) fn __rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceC1ERKS1_<
+ 'a,
+ 'b,
+ >(
+ __this: &'a mut crate::rust_std::mem::MaybeUninit<
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ __param_0: &'b crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ );
+ pub(crate) fn __rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceC1EOS1_<
+ 'a,
+ 'b,
+ >(
+ __this: &'a mut crate::rust_std::mem::MaybeUninit<
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ __param_0: ctor::RvalueReference<
+ 'b,
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ );
+ pub(crate) fn __rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceaSERKS1_<
+ 'a,
+ 'b,
+ >(
+ __this: crate::rust_std::pin::Pin<
+ &'a mut crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ __param_0: &'b crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ ) -> crate::rust_std::pin::Pin<
+ &'a mut crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >;
+ pub(crate) fn __rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceaSEOS1_<
+ 'a,
+ 'b,
+ >(
+ __this: crate::rust_std::pin::Pin<
+ &'a mut crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ __param_0: ctor::RvalueReference<
+ 'b,
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >,
+ ) -> crate::rust_std::pin::Pin<
+ &'a mut crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ >;
+ #[link_name = "_Z43useStructInInlineNamespaceWithFullQualifierN30test_namespace_bindings_inline5inner23StructInInlineNamespaceE"]
+ pub(crate) fn __rust_thunk___Z43useStructInInlineNamespaceWithFullQualifierN30test_namespace_bindings_inline5inner23StructInInlineNamespaceE(
+ s: crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ );
+ #[link_name = "_Z45useStructInInlineNamespaceSkipInlineQualifierN30test_namespace_bindings_inline5inner23StructInInlineNamespaceE"]
+ pub(crate) fn __rust_thunk___Z45useStructInInlineNamespaceSkipInlineQualifierN30test_namespace_bindings_inline5inner23StructInInlineNamespaceE(
+ s: crate::test_namespace_bindings_inline::inner::StructInInlineNamespace,
+ );
}
}
@@ -395,3 +641,22 @@
crate::test_namespace_bindings_reopened::inner::S: Drop
);
};
+
+const _: () = assert!(
+ rust_std::mem::size_of::<crate::test_namespace_bindings_inline::inner::StructInInlineNamespace>(
+ ) == 1
+);
+const _: () = assert!(
+ rust_std::mem::align_of::<crate::test_namespace_bindings_inline::inner::StructInInlineNamespace>(
+ ) == 1
+);
+const _: () = {
+ static_assertions::assert_not_impl_all!(
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace: Copy
+ );
+};
+const _: () = {
+ static_assertions::assert_not_impl_all!(
+ crate::test_namespace_bindings_inline::inner::StructInInlineNamespace: Drop
+ );
+};
diff --git a/rs_bindings_from_cc/test/golden/namespace_rs_api_impl.cc b/rs_bindings_from_cc/test/golden/namespace_rs_api_impl.cc
index 3f80136..70dabe1 100644
--- a/rs_bindings_from_cc/test/golden/namespace_rs_api_impl.cc
+++ b/rs_bindings_from_cc/test/golden/namespace_rs_api_impl.cc
@@ -81,6 +81,52 @@
class test_namespace_bindings_reopened::inner::S&& __param_0) {
return __this->operator=(std::forward<decltype(__param_0)>(__param_0));
}
+extern "C" void
+__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceC1Ev(
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace*
+ __this) {
+ crubit::construct_at(std::forward<decltype(__this)>(__this));
+}
+extern "C" void
+__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceC1ERKS1_(
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace*
+ __this,
+ const class test_namespace_bindings_inline::inner::StructInInlineNamespace&
+ __param_0) {
+ crubit::construct_at(std::forward<decltype(__this)>(__this),
+ std::forward<decltype(__param_0)>(__param_0));
+}
+extern "C" void
+__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceC1EOS1_(
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace*
+ __this,
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace&&
+ __param_0) {
+ crubit::construct_at(std::forward<decltype(__this)>(__this),
+ std::forward<decltype(__param_0)>(__param_0));
+}
+extern "C" void
+__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceD1Ev(
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace*
+ __this) {
+ std::destroy_at(std::forward<decltype(__this)>(__this));
+}
+extern "C" class test_namespace_bindings_inline::inner::StructInInlineNamespace&
+__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceaSERKS1_(
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace*
+ __this,
+ const class test_namespace_bindings_inline::inner::StructInInlineNamespace&
+ __param_0) {
+ return __this->operator=(std::forward<decltype(__param_0)>(__param_0));
+}
+extern "C" class test_namespace_bindings_inline::inner::StructInInlineNamespace&
+__rust_thunk___ZN30test_namespace_bindings_inline5inner23StructInInlineNamespaceaSEOS1_(
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace*
+ __this,
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace&&
+ __param_0) {
+ return __this->operator=(std::forward<decltype(__param_0)>(__param_0));
+}
static_assert(sizeof(class test_namespace_bindings::S) == 4);
static_assert(alignof(class test_namespace_bindings::S) == 4);
@@ -89,4 +135,13 @@
static_assert(sizeof(class test_namespace_bindings_reopened::inner::S) == 1);
static_assert(alignof(class test_namespace_bindings_reopened::inner::S) == 1);
+static_assert(
+ sizeof(
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace) ==
+ 1);
+static_assert(
+ alignof(
+ class test_namespace_bindings_inline::inner::StructInInlineNamespace) ==
+ 1);
+
#pragma clang diagnostic pop