Only emit a C++ thunk if there was Rust code generated for the same function.

A careful observer would note that it's still possible that a function _was_ generated, but that it doesn't call the C++ thunk, however, this is meant to be captured today by the "out of band" communication channel of `can_skip_cc_thunk`.

I think that, now that these can directly call each other, maybe we should retire `can_skip_cc_thunk` and instead feature this information in the return value of `generate_func`. But for now... fixed!

---

The fix itself is essentially two lines of code, but the change breaks many tests, which make assertions about the generated C++ thunks. If we remove the thunks, the tests fail! Where I was able to, I tried to keep (a version) of the test by fixing the C++ header so that it would emit functions. Where I didn't know how to do this (in particular, test_implicit_template_specializations_are_sorted_by_mangled_name), I deleted the broken assertions. (They did not seem critical to me, and the tests still otherwise are working and testing things.)

PiperOrigin-RevId: 463097005
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index c2a2293..2aec6f1 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -2185,8 +2185,8 @@
                 lifetime = quote! {#reference_lifetime};
             }
             RsTypeKind::Record { .. } => {
-                // This case doesn't happen for methods, but is needed for free functions mapped to
-                // a trait impl that take the first argument by value.
+                // This case doesn't happen for methods, but is needed for free functions mapped
+                // to a trait impl that take the first argument by value.
                 return Ok(quote! { self });
             }
             _ => bail!("Unexpected type of `self` parameter: {:?}", self),
@@ -2751,6 +2751,10 @@
         if can_skip_cc_thunk(db, func) {
             continue;
         }
+        if db.generate_func(func.clone()).unwrap_or_default().is_none() {
+            // No function was generated that will call this thunk.
+            continue;
+        }
 
         let thunk_ident = thunk_ident(func);
         let implementation_function = match &func.name {
@@ -3218,21 +3222,25 @@
 
     #[test]
     fn test_simple_struct() -> Result<()> {
-        let ir = ir_from_cc(&tokens_to_string(quote! {
+        let ir = ir_from_cc(
+            r#"
+            #pragma clang lifetime_elision
             struct SomeStruct final {
+                ~SomeStruct() {}
                 int public_int;
               protected:
                 int protected_int;
               private:
                int private_int;
             };
-        })?)?;
+        "#,
+        )?;
 
         let BindingsTokens { rs_api, rs_api_impl } = generate_bindings_tokens(ir)?;
         assert_rs_matches!(
             rs_api,
             quote! {
-                #[derive(Clone, Copy)]
+                #[::ctor::recursively_pinned(PinnedDrop)]
                 #[repr(C, align(4))]
                 pub struct SomeStruct {
                     __non_field_data: [::std::mem::MaybeUninit<u8>; 0],
@@ -3250,9 +3258,8 @@
                 const _: () = assert!(::std::mem::size_of::<Option<&i32>>() == ::std::mem::size_of::<&i32>());
                 const _: () = assert!(::std::mem::size_of::<crate::SomeStruct>() == 12);
                 const _: () = assert!(::std::mem::align_of::<crate::SomeStruct>() == 4);
-                const _: () = { static_assertions::assert_impl_all!(crate::SomeStruct: Clone); };
-                const _: () = { static_assertions::assert_impl_all!(crate::SomeStruct: Copy); };
-                const _: () = { static_assertions::assert_not_impl_any!(crate::SomeStruct: Drop); };
+                const _: () = { static_assertions::assert_not_impl_any!(crate::SomeStruct: Copy); };
+                const _: () = { static_assertions::assert_impl_all!(crate::SomeStruct: Drop); };
                 const _: () = assert!(memoffset_unstable_const::offset_of!(crate::SomeStruct, public_int) == 0);
                 const _: () = assert!(memoffset_unstable_const::offset_of!(crate::SomeStruct, protected_int) == 4);
                 const _: () = assert!(memoffset_unstable_const::offset_of!(crate::SomeStruct, private_int) == 8);
@@ -3279,10 +3286,20 @@
 
     #[test]
     fn test_struct_vs_class() -> Result<()> {
-        let ir = ir_from_cc(&tokens_to_string(quote! {
-            struct SomeStruct final { int field; };
-            class SomeClass final { int field; };
-        })?)?;
+        let ir = ir_from_cc(
+            r#"
+            #pragma clang lifetime_elision
+            struct SomeStruct final {
+                SomeStruct() {}
+                int field;
+            };
+            class SomeClass final {
+              public:
+                SomeClass() {}
+                int field;
+            };
+        "#,
+        )?;
         let BindingsTokens { rs_api, rs_api_impl } = generate_bindings_tokens(ir)?;
 
         // A Rust `struct` is generated for both `SomeStruct` and `SomeClass`.
@@ -4475,6 +4492,7 @@
     fn test_basic_union() -> Result<()> {
         let ir = ir_from_cc(
             r#"
+            #pragma clang lifetime_elision
             union SomeUnion {
                 int some_field;
                 long long some_bigger_field;
@@ -4500,19 +4518,6 @@
                 extern "C" void __rust_thunk___ZN9SomeUnionC1Ev(union SomeUnion*__this) {...}
             }
         );
-        assert_cc_matches!(
-            rs_api_impl,
-            quote! {
-                extern "C" void __rust_thunk___ZN9SomeUnionD1Ev(union SomeUnion*__this) {...}
-            }
-        );
-        assert_cc_matches!(
-            rs_api_impl,
-            quote! {
-                extern "C" union SomeUnion* __rust_thunk___ZN9SomeUnionaSERKS_(
-                    union SomeUnion*__this, const union SomeUnion* __param_0) { ... }
-            }
-        );
         assert_cc_matches!(rs_api_impl, quote! { static_assert(sizeof(union SomeUnion)==8) });
         assert_cc_matches!(rs_api_impl, quote! { static_assert(alignof(union SomeUnion)==8) });
         assert_cc_matches!(
@@ -5077,9 +5082,7 @@
         assert_rs_not_matches!(rs_api, quote! {impl Drop});
         assert_rs_not_matches!(rs_api, quote! {impl ::ctor::PinnedDrop});
         assert_rs_matches!(rs_api, quote! {pub x: i32});
-        // TODO(b/213326125): Avoid generating thunk impls that are never called.
-        // (The test assertion below should be reversed once this bug is fixed.)
-        assert_cc_matches!(rs_api_impl, quote! { std::destroy_at });
+        assert_cc_not_matches!(rs_api_impl, quote! { std::destroy_at });
         Ok(())
     }
 
@@ -6404,9 +6407,6 @@
                     test_namespace_bindings::f();
                 }
                 ...
-                extern "C" void __rust_thunk___ZN23test_namespace_bindings1SC1Ev(
-                    struct test_namespace_bindings::S* __this) {...}
-                ...
                 extern "C" void __rust_thunk___Z4useSN23test_namespace_bindings1SE(
                     struct test_namespace_bindings::S s) { useS(s); }
                 ...
@@ -6497,14 +6497,6 @@
             }
         );
 
-        // Constructors in mangled name order
-        let my_struct_bool_constructor =
-            make_rs_ident("__rust_thunk___ZN8MyStructIbEC1Ev__2f_2ftest_3atesting_5ftarget");
-        let my_struct_double_constructor =
-            make_rs_ident("__rust_thunk___ZN8MyStructIdEC1Ev__2f_2ftest_3atesting_5ftarget");
-        let my_struct_int_constructor =
-            make_rs_ident("__rust_thunk___ZN8MyStructIiEC1Ev__2f_2ftest_3atesting_5ftarget");
-
         // User defined methods in mangled name order
         let my_struct_bool_method =
             make_rs_ident("__rust_thunk___ZN8MyStructIbE4getTEv__2f_2ftest_3atesting_5ftarget");
@@ -6517,9 +6509,6 @@
             &bindings.rs_api_impl,
             quote! {
                 ...
-                extern "C" void #my_struct_bool_constructor(struct MyStruct<bool>*__this) {...} ...
-                extern "C" void #my_struct_double_constructor(struct MyStruct<double>*__this) {...} ...
-                extern "C" void #my_struct_int_constructor(struct MyStruct<int>*__this) {...} ...
                 extern "C" bool #my_struct_bool_method(struct MyStruct<bool>*__this) {...} ...
                 extern "C" double #my_struct_double_method(struct MyStruct<double>*__this) {...} ...
                 extern "C" int #my_struct_int_method(struct MyStruct<int>*__this) {...} ...