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)
}
}