Skip to content

Commit 480cad9

Browse files
committed
Decouple objc2 CF helper impls from objc2-core-foundation
This allows compiling `objc2-io-bluetooth-ui` without having to enable the `objc2-core-foundation` feature of `objc2-io-bluetooth`.
1 parent 756aee9 commit 480cad9

File tree

12 files changed

+116
-73
lines changed

12 files changed

+116
-73
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/header-translator/src/stmt.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,7 +2042,7 @@ impl Stmt {
20422042
}
20432043
Self::OpaqueDecl { is_cf, .. } => {
20442044
if *is_cf {
2045-
vec![ItemTree::cf("cf_type")]
2045+
vec![ItemTree::cf("cf_type"), ItemTree::objc("cf_objc2_type")]
20462046
} else {
20472047
vec![ItemTree::objc("Encoding")]
20482048
}
@@ -3094,7 +3094,6 @@ impl Stmt {
30943094
// SAFETY: The type is a CoreFoundation type, and
30953095
// correctly declared as a #[repr(C)] ZST.
30963096
writeln!(f, "cf_type!(")?;
3097-
writeln!(f, " #[encoding_name = {encoding_name:?}]")?;
30983097

30993098
// SAFETY: It's fine to implement helper traits for
31003099
// all generics (e.g. all of `CFArray<u32>`,
@@ -3114,6 +3113,22 @@ impl Stmt {
31143113
}
31153114
writeln!(f, " {{}}")?;
31163115
writeln!(f, ");")?;
3116+
3117+
let required_items = self
3118+
.required_items()
3119+
.chain(iter::once(ItemTree::objc("cf_objc2_type")));
3120+
let cfg_objc2 = self.cfg_gate_ln_for(required_items, config);
3121+
write!(f, "{cfg_objc2}")?;
3122+
writeln!(f, "cf_objc2_type!(")?;
3123+
// SAFETY: The type is a CoreFoundation type.
3124+
writeln!(
3125+
f,
3126+
" unsafe impl{} RefEncode<{encoding_name:?}> for {}{} {{}}",
3127+
GenericParamsHelper(generics, "?Sized"),
3128+
id.name,
3129+
GenericTyHelper(generics),
3130+
)?;
3131+
writeln!(f, ");")?;
31173132
} else {
31183133
let required_items = self
31193134
.required_items()

crates/objc2/src/__framework_prelude.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ pub use crate::runtime::{
1010
AnyClass, AnyObject, AnyProtocol, Bool, Imp, NSObject, NSObjectProtocol, ProtocolObject, Sel,
1111
};
1212
pub use crate::{
13-
extern_class, extern_methods, extern_protocol, ClassType, MainThreadMarker, MainThreadOnly,
14-
Message, ProtocolType,
13+
cf_objc2_type, extern_class, extern_methods, extern_protocol, ClassType, MainThreadMarker,
14+
MainThreadOnly, Message, ProtocolType,
1515
};

crates/objc2/src/__macro_helpers/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub use core::default::Default;
66
pub use core::fmt;
77
pub use core::hash::{Hash, Hasher};
88
pub use core::marker::{PhantomData, Sized};
9-
pub use core::mem::{size_of, ManuallyDrop, MaybeUninit};
9+
pub use core::mem::{size_of, transmute, ManuallyDrop, MaybeUninit};
1010
pub use core::ops::Deref;
1111
pub use core::option::Option::{self, None, Some};
1212
pub use core::primitive::{bool, isize, str, u8};
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/// Helper macro for implementing [`objc2`][crate] traits for
2+
/// CoreFoundation-like types.
3+
#[doc(hidden)] // For now, though still a breaking change to modify
4+
#[macro_export]
5+
macro_rules! cf_objc2_type {
6+
(unsafe impl $(<$($generic:ident : ?$sized:ident),* $(,)?>)? RefEncode<$encoding_name:literal> for $ty:ty {}) => {
7+
// SAFETY: Caller upholds that the struct is a ZST type, and
8+
// represents a C struct with the given encoding.
9+
unsafe impl $(<$($generic : ?$sized),*>)? $crate::encode::RefEncode for $ty {
10+
const ENCODING_REF: $crate::encode::Encoding = $crate::encode::Encoding::Pointer(
11+
&$crate::encode::Encoding::Struct($encoding_name, &[]),
12+
);
13+
}
14+
15+
// SAFETY: CF types are message-able in the Objective-C runtime.
16+
//
17+
// (Yes, even e.g. `CFArray<u32>`, though the return type from methods
18+
// might not be what's expected).
19+
unsafe impl $(<$($generic : ?$sized),*>)? $crate::Message for $ty {}
20+
21+
// Allow converting to AnyObject.
22+
// Similar to __extern_class_impl_as_ref_borrow!
23+
impl $(<$($generic : ?$sized),*>)? $crate::__macro_helpers::AsRef<$crate::runtime::AnyObject> for $ty {
24+
#[inline]
25+
fn as_ref(&self) -> &$crate::runtime::AnyObject {
26+
// SAFETY: CF types are valid to re-interpret as AnyObject.
27+
unsafe { $crate::__macro_helpers::transmute(self) }
28+
}
29+
}
30+
31+
impl $(<$($generic : ?$sized),*>)? $crate::__macro_helpers::Borrow<$crate::runtime::AnyObject> for $ty {
32+
#[inline]
33+
fn borrow(&self) -> &$crate::runtime::AnyObject {
34+
<Self as $crate::__macro_helpers::AsRef<$crate::runtime::AnyObject>>::as_ref(self)
35+
}
36+
}
37+
38+
// Do not implement `ClassType`, CoreFoundation objects are root
39+
// objects, and all inherit from the same (hidden) __NSCFType class.
40+
//
41+
// This also means that casting etc. must be implemented differently
42+
// for CoreFoundation objects (compare).
43+
44+
// NOTE: Make sure to keep objc2-core-foundation/src/base.rs up to
45+
// date with changes in here.
46+
};
47+
}

crates/objc2/src/macros/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod __method_msg_send;
44
mod __msg_send_parse;
55
mod __rewrite_self_param;
66
mod available;
7+
mod cf_objc2_type;
78
mod define_class;
89
mod extern_class;
910
mod extern_methods;

framework-crates/objc2-core-foundation/src/base.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,32 @@ impl hash::Hash for CFType {
188188
}
189189
}
190190

191-
crate::__cf_type_objc2!(impl () CFType, crate::__cf_macro_helpers::Encoding::Void);
191+
// SAFETY: CFType is defined as the following in the header:
192+
// typedef const CF_BRIDGED_TYPE(id) void * CFTypeRef;
193+
#[cfg(feature = "objc2")]
194+
unsafe impl objc2::encode::RefEncode for CFType {
195+
const ENCODING_REF: objc2::encode::Encoding =
196+
objc2::encode::Encoding::Pointer(&objc2::encode::Encoding::Void);
197+
}
198+
199+
// SAFETY: CF types are message-able in the Objective-C runtime.
200+
#[cfg(feature = "objc2")]
201+
unsafe impl objc2::Message for CFType {}
202+
203+
#[cfg(feature = "objc2")]
204+
impl AsRef<objc2::runtime::AnyObject> for CFType {
205+
fn as_ref(&self) -> &objc2::runtime::AnyObject {
206+
// SAFETY: CFType is valid to re-interpret as AnyObject.
207+
unsafe { core::mem::transmute(self) }
208+
}
209+
}
210+
211+
#[cfg(feature = "objc2")]
212+
impl core::borrow::Borrow<objc2::runtime::AnyObject> for CFType {
213+
fn borrow(&self) -> &objc2::runtime::AnyObject {
214+
<Self as AsRef<objc2::runtime::AnyObject>>::as_ref(self)
215+
}
216+
}
192217

193218
// NOTE: impl AsRef<CFType> for AnyObject would probably not be valid, since
194219
// not all Objective-C objects can be used as CoreFoundation objects (?)

framework-crates/objc2-core-foundation/src/cf_type.rs

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#[macro_export]
3030
macro_rules! cf_type {
3131
(
32-
#[encoding_name = $encoding_name:expr]
3332
unsafe impl $(<$($generic:ident : ?$sized:ident),* $(,)?>)? $ty:ident $(<$($generic_param:ident),* $(,)?>)? $(: $superclass:ty)? {}
3433
) => {
3534
// Reflexive AsRef impl.
@@ -46,12 +45,6 @@ macro_rules! cf_type {
4645
$crate::__cf_type_needs_cf_base!(impl ($(<$($generic : ?$sized),*>)?) $ty $(<$($generic_param),*>)?);
4746

4847
$crate::__cf_type_superclass!(impl ($(<$($generic : ?$sized),*>)?) $ty $(<$($generic_param),*>)? $(: $superclass)?);
49-
50-
// Objective-C interop
51-
$crate::__cf_type_objc2!(
52-
impl ($(<$($generic : ?$sized),*>)?) $ty $(<$($generic_param),*>)?,
53-
$crate::__cf_macro_helpers::Encoding::Struct($encoding_name, &[])
54-
);
5548
};
5649
}
5750

@@ -182,53 +175,3 @@ macro_rules! __cf_type_no_superclass {
182175
macro_rules! __cf_type_no_superclass {
183176
(impl ($($generics:tt)*) $ty:ty) => {};
184177
}
185-
186-
#[cfg(feature = "objc2")]
187-
#[doc(hidden)]
188-
#[macro_export]
189-
macro_rules! __cf_type_objc2 {
190-
(impl ($($generics:tt)*) $ty:ty, $encoding:expr) => {
191-
// SAFETY: Caller upholds that the struct is a ZST type, and
192-
// represents a C struct with the given encoding.
193-
unsafe impl $($generics)* $crate::__cf_macro_helpers::RefEncode for $ty {
194-
const ENCODING_REF: $crate::__cf_macro_helpers::Encoding =
195-
$crate::__cf_macro_helpers::Encoding::Pointer(&$encoding);
196-
}
197-
198-
// SAFETY: CF types are message-able in the Objective-C runtime.
199-
//
200-
// (Yes, even e.g. `CFArray<u32>`, though the return type from methods
201-
// might not be what's expected).
202-
unsafe impl $($generics)* $crate::__cf_macro_helpers::Message for $ty {}
203-
204-
// Allow converting to AnyObject.
205-
// Similar to objc2::__extern_class_impl_as_ref_borrow!
206-
impl $($generics)* $crate::__cf_macro_helpers::AsRef<$crate::__cf_macro_helpers::AnyObject> for $ty {
207-
#[inline]
208-
fn as_ref(&self) -> &$crate::__cf_macro_helpers::AnyObject {
209-
// SAFETY: CF types are valid to re-interpret as AnyObject.
210-
unsafe { $crate::__cf_macro_helpers::transmute(self) }
211-
}
212-
}
213-
214-
impl $($generics)* $crate::__cf_macro_helpers::Borrow<$crate::__cf_macro_helpers::AnyObject> for $ty {
215-
#[inline]
216-
fn borrow(&self) -> &$crate::__cf_macro_helpers::AnyObject {
217-
<Self as $crate::__cf_macro_helpers::AsRef<$crate::__cf_macro_helpers::AnyObject>>::as_ref(self)
218-
}
219-
}
220-
221-
// Do not implement `ClassType`, CoreFoundation objects are root
222-
// objects, and all inherit from the same (hidden) __NSCFType class.
223-
//
224-
// This also means that casting etc. must be implemented differently
225-
// for CoreFoundation objects (compare).
226-
};
227-
}
228-
229-
#[cfg(not(feature = "objc2"))]
230-
#[doc(hidden)]
231-
#[macro_export]
232-
macro_rules! __cf_type_objc2 {
233-
($($t:tt)*) => {};
234-
}

framework-crates/objc2-disk-arbitration/Cargo.toml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

framework-crates/objc2-io-surface/src/io_surface.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,10 @@ pub struct IOSurfaceRef {
1010

1111
#[cfg(feature = "objc2-core-foundation")]
1212
objc2_core_foundation::cf_type!(
13-
#[encoding_name = "__IOSurface"]
1413
unsafe impl IOSurfaceRef {}
1514
);
1615

17-
// Hacky fix for `IOSurfaceRef` being used without `objc2-core-foundation`
18-
// being enabled.
19-
#[cfg(all(not(feature = "objc2-core-foundation"), feature = "objc2"))]
20-
unsafe impl objc2::encode::RefEncode for IOSurfaceRef {
21-
const ENCODING_REF: objc2::encode::Encoding =
22-
objc2::encode::Encoding::Pointer(&objc2::encode::Encoding::Struct("__IOSurface", &[]));
23-
}
16+
#[cfg(feature = "objc2")]
17+
objc2::cf_objc2_type!(
18+
unsafe impl RefEncode<"__IOSurface"> for IOSurfaceRef {}
19+
);

0 commit comments

Comments
 (0)