From 9d8c74ea343dc06fcc2bb1c33fce97bbc506bcc8 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 13 Aug 2024 04:13:17 -0700 Subject: [PATCH] Fix TCFType macros for generic types (#652) * Improve TCFType macros This adds the following new features: * `declare_TCFType!`: Generics are accepted. * `impl_TCFType!`: Non-defaulted generics are accepted, and impls are fixed to be for all generics. In addition, some warnings are silenced and the macros no longer depend on any traits being in scope in the caller. * Support generics in impl_CFComparison * Add generic test for macros --- core-foundation/src/characterset.rs | 2 - core-foundation/src/lib.rs | 59 +++++++++++++------ .../tests/use_macro_outside_crate.rs | 5 ++ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/core-foundation/src/characterset.rs b/core-foundation/src/characterset.rs index c10a0bd..ec93d8e 100644 --- a/core-foundation/src/characterset.rs +++ b/core-foundation/src/characterset.rs @@ -11,8 +11,6 @@ pub use core_foundation_sys::characterset::*; -use crate::base::TCFType; - declare_TCFType! { /// An immutable set of Unicode characters. CFCharacterSet, CFCharacterSetRef diff --git a/core-foundation/src/lib.rs b/core-foundation/src/lib.rs index d3cb019..127c246 100644 --- a/core-foundation/src/lib.rs +++ b/core-foundation/src/lib.rs @@ -53,15 +53,24 @@ macro_rules! declare_TCFType { $(#[$doc:meta])* $ty:ident, $raw:ident ) => { - $(#[$doc])* - pub struct $ty($raw); + declare_TCFType!($(#[$doc])* $ty<>, $raw); + }; - impl Drop for $ty { + ( + $(#[$doc:meta])* + $ty:ident<$($p:ident $(: $bound:path)*),*>, $raw:ident + ) => { + $(#[$doc])* + pub struct $ty<$($p $(: $bound)*),*>($raw, $(::std::marker::PhantomData<$p>),*); + + #[allow(unused_imports)] + impl<$($p $(: $bound)*),*> Drop for $ty<$($p),*> { fn drop(&mut self) { + use $crate::base::TCFType; unsafe { $crate::base::CFRelease(self.as_CFTypeRef()) } } } - } + }; } /// Provide an implementation of the [`TCFType`] trait for the Rust @@ -82,6 +91,7 @@ macro_rules! impl_TCFType { impl<$($p $(: $bound)*),*> $crate::base::TCFType for $ty<$($p),*> { type Ref = $ty_ref; + #[allow(non_snake_case)] #[inline] fn as_concrete_TypeRef(&self) -> $ty_ref { self.0 @@ -94,6 +104,7 @@ macro_rules! impl_TCFType { $crate::base::TCFType::wrap_under_create_rule(reference) } + #[allow(non_snake_case)] #[inline] fn as_CFTypeRef(&self) -> $crate::base::CFTypeRef { self.as_concrete_TypeRef() as $crate::base::CFTypeRef @@ -115,39 +126,46 @@ macro_rules! impl_TCFType { } } - impl Clone for $ty { + #[allow(unused_imports)] + impl<$($p $(: $bound)*),*> Clone for $ty<$($p),*> { #[inline] - fn clone(&self) -> $ty { + fn clone(&self) -> Self { + use $crate::base::TCFType; unsafe { $ty::wrap_under_get_rule(self.0) } } } - impl PartialEq for $ty { + #[allow(unused_imports)] + impl<$($p $(: $bound)*),*> PartialEq for $ty<$($p),*> { #[inline] - fn eq(&self, other: &$ty) -> bool { + fn eq(&self, other: &Self) -> bool { + use $crate::base::TCFType; self.as_CFType().eq(&other.as_CFType()) } } - impl Eq for $ty { } + impl<$($p $(: $bound)*),*> Eq for $ty<$($p),*> { } - unsafe impl<'a> $crate::base::ToVoid<$ty> for &'a $ty { + #[allow(unused_imports)] + unsafe impl<'a, $($p $(: $bound)*),*> $crate::base::ToVoid<$ty<$($p),*>> for &'a $ty<$($p),*> { fn to_void(&self) -> *const ::core::ffi::c_void { - use $crate::base::TCFTypeRef; + use $crate::base::{TCFType, TCFTypeRef}; self.as_concrete_TypeRef().as_void_ptr() } } - unsafe impl $crate::base::ToVoid<$ty> for $ty { + #[allow(unused_imports)] + unsafe impl<$($p $(: $bound)*),*> $crate::base::ToVoid<$ty<$($p),*>> for $ty<$($p),*> { fn to_void(&self) -> *const ::core::ffi::c_void { - use $crate::base::TCFTypeRef; + use $crate::base::{TCFType, TCFTypeRef}; self.as_concrete_TypeRef().as_void_ptr() } } - unsafe impl $crate::base::ToVoid<$ty> for $ty_ref { + #[allow(unused_imports)] + unsafe impl<$($p $(: $bound)*),*> $crate::base::ToVoid<$ty<$($p),*>> for $ty_ref { fn to_void(&self) -> *const ::core::ffi::c_void { use $crate::base::TCFTypeRef; self.as_void_ptr() @@ -178,8 +196,10 @@ macro_rules! impl_CFTypeDescription { impl_CFTypeDescription!($ty<>); }; ($ty:ident<$($p:ident $(: $bound:path)*),*>) => { + #[allow(unused_imports)] impl<$($p $(: $bound)*),*> ::std::fmt::Debug for $ty<$($p),*> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + use $crate::base::TCFType; self.as_CFType().fmt(f) } } @@ -189,9 +209,12 @@ macro_rules! impl_CFTypeDescription { #[macro_export] macro_rules! impl_CFComparison { ($ty:ident, $compare:ident) => { - impl PartialOrd for $ty { + impl_CFComparison!($ty<>, $compare); + }; + ($ty:ident<$($p:ident $(: $bound:path)*),*>, $compare:ident) => { + impl<$($p $(: $bound)*),*> PartialOrd for $ty<$($p),*> { #[inline] - fn partial_cmp(&self, other: &$ty) -> Option<::std::cmp::Ordering> { + fn partial_cmp(&self, other: &$ty<$($p),*>) -> Option<::std::cmp::Ordering> { unsafe { Some( $compare( @@ -205,9 +228,9 @@ macro_rules! impl_CFComparison { } } - impl Ord for $ty { + impl<$($p $(: $bound)*),*> Ord for $ty<$($p),*> { #[inline] - fn cmp(&self, other: &$ty) -> ::std::cmp::Ordering { + fn cmp(&self, other: &$ty<$($p),*>) -> ::std::cmp::Ordering { self.partial_cmp(other).unwrap() } } diff --git a/core-foundation/tests/use_macro_outside_crate.rs b/core-foundation/tests/use_macro_outside_crate.rs index a249d45..0f2d926 100644 --- a/core-foundation/tests/use_macro_outside_crate.rs +++ b/core-foundation/tests/use_macro_outside_crate.rs @@ -24,3 +24,8 @@ declare_TCFType!(CFFooBar, CFFooBarRef); impl_TCFType!(CFFooBar, CFFooBarRef, CFFooBarGetTypeID); impl_CFTypeDescription!(CFFooBar); impl_CFComparison!(CFFooBar, fake_compare); + +declare_TCFType!(CFGenericFooBar, CFFooBarRef); +impl_TCFType!(CFGenericFooBar, CFFooBarRef, CFFooBarGetTypeID); +impl_CFTypeDescription!(CFGenericFooBar); +impl_CFComparison!(CFGenericFooBar, fake_compare);