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