Support fieldless `recursively_pinned` structs and enums.

(In the case of structs, that's empty structs -- in the case of enums, it's C-like enums.)

PiperOrigin-RevId: 447449578
diff --git a/rs_bindings_from_cc/support/ctor_proc_macros.rs b/rs_bindings_from_cc/support/ctor_proc_macros.rs
index 36b44d4..5a7bd0f 100644
--- a/rs_bindings_from_cc/support/ctor_proc_macros.rs
+++ b/rs_bindings_from_cc/support/ctor_proc_macros.rs
@@ -98,16 +98,29 @@
     projected.ident = projected_ident(&projected.ident);
     let projected_ident = &projected.ident;
 
-    let lifetime = syn::Lifetime::new("'proj", Span::call_site());
     assert_eq!(
         projected.generics.params.len(),
         0,
         "pin projection is currently not implemented for generic structs"
     );
-    projected
-        .generics
-        .params
-        .push(syn::GenericParam::Lifetime(syn::LifetimeDef::new(lifetime.clone())));
+
+    let is_fieldless = match &projected.data {
+        syn::Data::Struct(data) => data.fields.is_empty(),
+        syn::Data::Enum(e) => e.variants.iter().all(|variant| variant.fields.is_empty()),
+        syn::Data::Union(_) => unimplemented!(),
+    };
+
+    let lifetime;
+    if is_fieldless {
+        lifetime = quote! {};
+    } else {
+        let syn_lifetime = syn::Lifetime::new("'proj", Span::call_site());
+        projected
+            .generics
+            .params
+            .push(syn::GenericParam::Lifetime(syn::LifetimeDef::new(syn_lifetime.clone())));
+        lifetime = quote! {#syn_lifetime};
+    }
 
     let project_field = |field: &mut syn::Field| {
         field.attrs.clear();
@@ -219,7 +232,9 @@
         #projected_impl
 
         impl #name {
-            fn project(self: ::std::pin::Pin<&mut Self>) -> #projected_ident<'_> {
+            #[must_use]
+            #[inline(always)]
+            fn project(self: ::std::pin::Pin<&mut Self>) -> #projected_ident {
                 #projected_ident::new(self)
             }
         }