From 4d944aaafee868f38f314c9780241363291cce70 Mon Sep 17 00:00:00 2001 From: roblabla Date: Thu, 11 Apr 2024 11:10:41 +0200 Subject: [PATCH] Better generic support in implement --- crates/libs/implement/src/lib.rs | 57 +++++++++++++------------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/crates/libs/implement/src/lib.rs b/crates/libs/implement/src/lib.rs index f1cbeec5446..750dbbbaa49 100644 --- a/crates/libs/implement/src/lib.rs +++ b/crates/libs/implement/src/lib.rs @@ -42,19 +42,8 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: let original_type2 = original_type.clone(); let original_type2 = syn::parse_macro_input!(original_type2 as syn::ItemStruct); let original_ident = original_type2.ident; - let mut constraints = quote! {}; - if let Some(where_clause) = original_type2.generics.where_clause { - where_clause.predicates.to_tokens(&mut constraints); - } - - let generics = if original_type2.generics.lt_token.is_some() { - let mut params = quote! {}; - original_type2.generics.params.to_tokens(&mut params); - quote! { <#params> } - } else { - quote! { <> } - }; + let (impl_generics, type_generics, where_clause) = original_type2.generics.split_for_impl(); let impl_ident = quote::format_ident!("{}_Impl", original_ident); let vtbl_idents = attributes.implement.iter().map(|implement| implement.to_vtbl_ident()); @@ -63,7 +52,7 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: let vtable_news = attributes.implement.iter().enumerate().map(|(enumerate, implement)| { let vtbl_ident = implement.to_vtbl_ident(); let offset = proc_macro2::Literal::isize_unsuffixed(-1 - enumerate as isize); - quote! { #vtbl_ident::new::() } + quote! { #vtbl_ident::new::() } }); let offset = attributes.implement.iter().enumerate().map(|(offset, _)| proc_macro2::Literal::usize_unsuffixed(offset)); @@ -84,23 +73,23 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: let interface_ident = implement.to_ident(); let offset = proc_macro2::Literal::usize_unsuffixed(enumerate); quote! { - impl #generics ::core::convert::From<#original_ident::#generics> for #interface_ident where #constraints { - fn from(this: #original_ident::#generics) -> Self { - let this = #impl_ident::#generics::new(this); + impl #impl_generics ::core::convert::From<#original_ident::#type_generics> for #interface_ident #where_clause { + fn from(this: #original_ident::#type_generics) -> Self { + let this = #impl_ident::#type_generics::new(this); let mut this = ::core::mem::ManuallyDrop::new(::std::boxed::Box::new(this)); let vtable_ptr = &this.vtables.#offset; // SAFETY: interfaces are in-memory equivalent to pointers to their vtables. unsafe { ::core::mem::transmute(vtable_ptr) } } } - impl #generics ::windows::core::AsImpl<#original_ident::#generics> for #interface_ident where #constraints { + impl #impl_generics ::windows::core::AsImpl<#original_ident::#type_generics> for #interface_ident #where_clause { // SAFETY: the offset is guranteed to be in bounds, and the implementation struct // is guaranteed to live at least as long as `self`. - unsafe fn as_impl(&self) -> &#original_ident::#generics { + unsafe fn as_impl(&self) -> &#original_ident::#type_generics { let this = ::windows::core::Interface::as_raw(self); // Subtract away the vtable offset plus 1, for the `identity` field, to get // to the impl struct which contains that original implementation type. - let this = (this as *mut *mut ::core::ffi::c_void).sub(1 + #offset) as *mut #impl_ident::#generics; + let this = (this as *mut *mut ::core::ffi::c_void).sub(1 + #offset) as *mut #impl_ident::#type_generics; &(*this).this } } @@ -109,16 +98,16 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: let tokens = quote! { #[repr(C)] - struct #impl_ident #generics where #constraints { + struct #impl_ident #impl_generics #where_clause { identity: *const ::windows::core::IInspectable_Vtbl, vtables: (#(*const #vtbl_idents,)*), - this: #original_ident::#generics, + this: #original_ident::#type_generics, count: ::windows::core::imp::WeakRefCount, } - impl #generics #impl_ident::#generics where #constraints { + impl #impl_generics #impl_ident::#type_generics #where_clause { const VTABLES: (#(#vtbl_idents2,)*) = (#(#vtable_news,)*); const IDENTITY: ::windows::core::IInspectable_Vtbl = ::windows::core::IInspectable_Vtbl::new::(); - fn new(this: #original_ident::#generics) -> Self { + fn new(this: #original_ident::#type_generics) -> Self { Self { identity: &Self::IDENTITY, vtables:(#(&Self::VTABLES.#offset,)*), @@ -127,8 +116,8 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: } } } - impl #generics ::windows::core::IUnknownImpl for #impl_ident::#generics where #constraints { - type Impl = #original_ident::#generics; + impl #impl_generics ::windows::core::IUnknownImpl for #impl_ident::#type_generics #where_clause { + type Impl = #original_ident::#type_generics; fn get_impl(&self) -> &Self::Impl { &self.this } @@ -178,7 +167,7 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: ::windows::core::HRESULT(0) } } - impl #generics #original_ident::#generics where #constraints { + impl #impl_generics #original_ident::#type_generics #where_clause { /// Try casting as the provided interface /// /// # Safety @@ -186,23 +175,23 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro: /// This function can only be safely called if `self` has been heap allocated and pinned using /// the mechanisms provided by `implement` macro. unsafe fn cast(&self) -> ::windows::core::Result { - let boxed = (self as *const _ as *const *mut ::core::ffi::c_void).sub(1 + #interfaces_len) as *mut #impl_ident::#generics; + let boxed = (self as *const _ as *const *mut ::core::ffi::c_void).sub(1 + #interfaces_len) as *mut #impl_ident::#type_generics; let mut result = None; - <#impl_ident::#generics as ::windows::core::IUnknownImpl>::QueryInterface(&*boxed, &I::IID, &mut result as *mut _ as _).and_some(result) + <#impl_ident::#type_generics as ::windows::core::IUnknownImpl>::QueryInterface(&*boxed, &I::IID, &mut result as *mut _ as _).and_some(result) } } - impl #generics ::core::convert::From<#original_ident::#generics> for ::windows::core::IUnknown where #constraints { - fn from(this: #original_ident::#generics) -> Self { - let this = #impl_ident::#generics::new(this); + impl #impl_generics ::core::convert::From<#original_ident::#type_generics> for ::windows::core::IUnknown #where_clause { + fn from(this: #original_ident::#type_generics) -> Self { + let this = #impl_ident::#type_generics::new(this); let boxed = ::core::mem::ManuallyDrop::new(::std::boxed::Box::new(this)); unsafe { ::core::mem::transmute(&boxed.identity) } } } - impl #generics ::core::convert::From<#original_ident::#generics> for ::windows::core::IInspectable where #constraints { - fn from(this: #original_ident::#generics) -> Self { - let this = #impl_ident::#generics::new(this); + impl #impl_generics ::core::convert::From<#original_ident::#type_generics> for ::windows::core::IInspectable #where_clause { + fn from(this: #original_ident::#type_generics) -> Self { + let this = #impl_ident::#type_generics::new(this); let boxed = ::core::mem::ManuallyDrop::new(::std::boxed::Box::new(this)); unsafe { ::core::mem::transmute(&boxed.identity)