From 01f8bf4b795f86c057e8d0d29b49184a6c93bc6e Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 1 Sep 2022 01:11:17 +0200 Subject: [PATCH 1/3] Relax ?Sized bounds everywhere Possible since Message: Sized --- objc2-encode/src/encode.rs | 4 +- objc2/CHANGELOG.md | 4 ++ objc2/src/__macro_helpers.rs | 12 ++-- objc2/src/class_type.rs | 2 +- objc2/src/declare.rs | 10 ++-- objc2/src/declare/ivar_drop.rs | 11 ++-- objc2/src/foundation/array.rs | 48 ++++++++-------- objc2/src/foundation/copying.rs | 4 +- objc2/src/foundation/dictionary.rs | 36 ++++++++---- objc2/src/foundation/enumerator.rs | 22 ++++---- objc2/src/foundation/mutable_array.rs | 44 ++++++++------- objc2/src/foundation/mutable_dictionary.rs | 37 ++++++++---- objc2/src/foundation/mutable_set.rs | 34 +++++------ objc2/src/foundation/set.rs | 40 ++++++------- objc2/src/lib.rs | 2 + objc2/src/macros/extern_class.rs | 10 ++-- objc2/src/macros/extern_methods.rs | 4 +- objc2/src/message/mod.rs | 38 ++++++------- objc2/src/rc/allocated.rs | 4 +- objc2/src/rc/id.rs | 66 +++++++++++----------- objc2/src/rc/id_forwarding_impls.rs | 45 +++++++-------- objc2/src/rc/id_traits.rs | 10 ++-- objc2/src/rc/weak_id.rs | 30 +++++----- 23 files changed, 277 insertions(+), 240 deletions(-) diff --git a/objc2-encode/src/encode.rs b/objc2-encode/src/encode.rs index 8a7c206f6..afdd386b3 100644 --- a/objc2-encode/src/encode.rs +++ b/objc2-encode/src/encode.rs @@ -496,8 +496,8 @@ encode_pointer_impls!( /// well. So trying to do it quickly requires generating a polynomial amount of /// implementations, which IMO is overkill for such a small issue. /// -/// Using `?Sized` is probably not safe here because C functions can only take -/// and return items with a known size. +/// Using `?Sized` is not safe here because C functions can only take and +/// return items with a known size. macro_rules! encode_fn_pointer_impl { (@ $FnTy: ty, $($Arg: ident),*) => { unsafe impl Encode for $FnTy { diff --git a/objc2/CHANGELOG.md b/objc2/CHANGELOG.md index ed446dc83..44f5428c7 100644 --- a/objc2/CHANGELOG.md +++ b/objc2/CHANGELOG.md @@ -17,6 +17,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). determining the name of a specific class. * Allow directly specifying class name in declare_class! macro. +### Changed +* **BREAKING**: Slightly changed when a type implements `?Sized` to support + `extern type` in the future. In particular, `Message` now requires `Sized`. + ### Removed * **BREAKING**: `MaybeUninit` no longer implements `IvarType` directly; use `Ivar::write` instead. diff --git a/objc2/src/__macro_helpers.rs b/objc2/src/__macro_helpers.rs index f08afeb2f..e6a3fa473 100644 --- a/objc2/src/__macro_helpers.rs +++ b/objc2/src/__macro_helpers.rs @@ -1,7 +1,7 @@ use crate::__sel_inner; use crate::rc::{Allocated, Id, Ownership}; use crate::runtime::{Class, Object, Sel}; -use crate::{Message, MessageArguments, MessageReceiver}; +use crate::{Message, MessageArguments, MessageReceiver, Thin}; pub use crate::cache::CachedClass; pub use crate::cache::CachedSel; @@ -83,7 +83,7 @@ type Init = RetainSemantics; type CopyOrMutCopy = RetainSemantics; type Other = RetainSemantics; -pub trait MsgSendId { +pub trait MsgSendId { unsafe fn send_message_id>( obj: T, sel: Sel, @@ -162,7 +162,7 @@ impl MsgSendId f } } -impl MsgSendId for Other { +impl MsgSendId for Other { #[inline] #[track_caller] unsafe fn send_message_id>( @@ -186,14 +186,14 @@ impl MsgSendId for Other } } -pub trait MaybeUnwrap { +pub trait MaybeUnwrap { fn maybe_unwrap<'a, Failed: MsgSendIdFailed<'a>>( obj: Option>, args: Failed::Args, ) -> Self; } -impl MaybeUnwrap for Option> { +impl MaybeUnwrap for Option> { #[inline] #[track_caller] fn maybe_unwrap<'a, Failed: MsgSendIdFailed<'a>>( @@ -204,7 +204,7 @@ impl MaybeUnwrap for Option> { } } -impl MaybeUnwrap for Id { +impl MaybeUnwrap for Id { #[inline] #[track_caller] fn maybe_unwrap<'a, Failed: MsgSendIdFailed<'a>>( diff --git a/objc2/src/class_type.rs b/objc2/src/class_type.rs index 9ed2f4986..b47c8f9b3 100644 --- a/objc2/src/class_type.rs +++ b/objc2/src/class_type.rs @@ -67,7 +67,7 @@ pub unsafe trait ClassType: Message { /// [`Deref`]: std::ops::Deref /// [`Deref::Target`]: std::ops::Deref::Target /// [`runtime::Object`]: crate::runtime::Object - type Super: Message; + type Super: ?Sized + Message; /// The name of the Objective-C class that this type represents. const NAME: &'static str; diff --git a/objc2/src/declare.rs b/objc2/src/declare.rs index 21c3de3c4..cc9bcf756 100644 --- a/objc2/src/declare.rs +++ b/objc2/src/declare.rs @@ -127,7 +127,7 @@ use crate::encode::{Encode, EncodeArguments, Encoding, RefEncode}; use crate::ffi; use crate::runtime::{Bool, Class, Imp, Object, Protocol, Sel}; use crate::sel; -use crate::Message; +use crate::{Message, Thin}; pub use ivar::{InnerIvarType, Ivar, IvarType}; pub use ivar_drop::IvarDrop; @@ -142,7 +142,7 @@ pub(crate) mod private { /// function pointer types. pub trait MethodImplementation: private::Sealed { /// The callee type of the method. - type Callee: RefEncode + ?Sized; + type Callee: RefEncode + ?Sized + Thin; /// The return type of the method. type Ret: Encode; /// The argument types of the method. @@ -156,14 +156,14 @@ macro_rules! method_decl_impl { (@<$($l:lifetime),*> T, $r:ident, $f:ty, $($t:ident),*) => { impl<$($l,)* T, $r, $($t),*> private::Sealed for $f where - T: Message + ?Sized, + T: ?Sized + Message, $r: Encode, $($t: Encode,)* {} impl<$($l,)* T, $r, $($t),*> MethodImplementation for $f where - T: Message + ?Sized, + T: ?Sized + Message, $r: Encode, $($t: Encode,)* { @@ -336,7 +336,7 @@ impl ClassBuilder { /// when the method is invoked from Objective-C. pub unsafe fn add_method(&mut self, sel: Sel, func: F) where - T: Message + ?Sized, + T: ?Sized + Message, F: MethodImplementation, { let encs = F::Args::ENCODINGS; diff --git a/objc2/src/declare/ivar_drop.rs b/objc2/src/declare/ivar_drop.rs index 96aca758a..c25dc6277 100644 --- a/objc2/src/declare/ivar_drop.rs +++ b/objc2/src/declare/ivar_drop.rs @@ -98,7 +98,7 @@ unsafe impl InnerIvarType for IvarDrop>> { } } -impl super::ivar::private::Sealed for IvarDrop> {} +impl super::ivar::private::Sealed for IvarDrop> {} // SAFETY: `Id` is `NonNull`, and hence safe to store as a pointer. // // The user ensures that the Id has been initialized in an `init` method @@ -107,7 +107,7 @@ impl super::ivar::private::Sealed for IvarDrop>` // directly today, but since we can't do so for `Box` (because that is // `#[fundamental]`), I think it makes sense to handle them similarly. -unsafe impl InnerIvarType for IvarDrop> { +unsafe impl InnerIvarType for IvarDrop> { const __ENCODING: Encoding = <*const T as EncodeConvert>::__ENCODING; type __Inner = Option>; @@ -137,12 +137,15 @@ unsafe impl InnerIvarType for IvarDrop> { } } -impl super::ivar::private::Sealed for IvarDrop>> {} +impl super::ivar::private::Sealed + for IvarDrop>> +{ +} // SAFETY: `Id` guarantees the null-pointer optimization. // // This is valid to initialize as all-zeroes, so the user doesn't have to do // anything to initialize it. -unsafe impl InnerIvarType for IvarDrop>> { +unsafe impl InnerIvarType for IvarDrop>> { const __ENCODING: Encoding = <*const T as EncodeConvert>::__ENCODING; type __Inner = Option>; diff --git a/objc2/src/foundation/array.rs b/objc2/src/foundation/array.rs index f65873741..3bc5f05f6 100644 --- a/objc2/src/foundation/array.rs +++ b/objc2/src/foundation/array.rs @@ -52,29 +52,29 @@ __inner_extern_class!( // `T: PartialEq` bound correct because `NSArray` does deep (instead of // shallow) equality comparisons. #[derive(PartialEq, Eq, Hash)] - pub struct NSArray { + pub struct NSArray { item: PhantomData>, notunwindsafe: PhantomData<&'static mut ()>, } - unsafe impl ClassType for NSArray { + unsafe impl ClassType for NSArray { type Super = NSObject; } ); // SAFETY: Same as Id (which is what NSArray effectively stores). -unsafe impl Sync for NSArray {} -unsafe impl Send for NSArray {} -unsafe impl Sync for NSArray {} -unsafe impl Send for NSArray {} +unsafe impl Sync for NSArray {} +unsafe impl Send for NSArray {} +unsafe impl Sync for NSArray {} +unsafe impl Send for NSArray {} // Also same as Id -impl RefUnwindSafe for NSArray {} -impl UnwindSafe for NSArray {} -impl UnwindSafe for NSArray {} +impl RefUnwindSafe for NSArray {} +impl UnwindSafe for NSArray {} +impl UnwindSafe for NSArray {} #[track_caller] -pub(crate) unsafe fn with_objects( +pub(crate) unsafe fn with_objects( cls: &Class, objects: &[&T], ) -> Id { @@ -89,7 +89,7 @@ pub(crate) unsafe fn with_objects extern_methods!( /// Generic creation methods. - unsafe impl NSArray { + unsafe impl NSArray { /// Get an empty array. pub fn new() -> Id { // SAFETY: @@ -120,7 +120,7 @@ extern_methods!( } /// Creation methods that produce shared arrays. - unsafe impl NSArray { + unsafe impl NSArray { pub fn from_slice(slice: &[Id]) -> Id { // SAFETY: Taking `&T` would not be sound, since the `&T` could come // from an `Id` that would now no longer be owned! @@ -133,7 +133,7 @@ extern_methods!( } /// Generic accessor methods. - unsafe impl NSArray { + unsafe impl NSArray { #[doc(alias = "count")] #[sel(count)] pub fn len(&self) -> usize; @@ -200,7 +200,7 @@ extern_methods!( } /// Accessor methods that work on shared arrays. - unsafe impl NSArray { + unsafe impl NSArray { #[doc(alias = "objectAtIndex:")] pub fn get_retained(&self, index: usize) -> Id { let obj = self.get(index).unwrap(); @@ -217,7 +217,7 @@ extern_methods!( } /// Accessor methods that work on owned arrays. - unsafe impl NSArray { + unsafe impl NSArray { #[doc(alias = "objectAtIndex:")] pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { // TODO: Replace this check with catching the thrown NSRangeException @@ -242,28 +242,28 @@ extern_methods!( /// This is implemented as a shallow copy. /// /// As such, it is only possible when the array's contents are `Shared`. -unsafe impl NSCopying for NSArray { +unsafe impl NSCopying for NSArray { type Ownership = Shared; type Output = NSArray; } /// This is implemented as a shallow copy. -unsafe impl NSMutableCopying for NSArray { +unsafe impl NSMutableCopying for NSArray { type Output = NSMutableArray; } -impl alloc::borrow::ToOwned for NSArray { +impl alloc::borrow::ToOwned for NSArray { type Owned = Id, Shared>; fn to_owned(&self) -> Self::Owned { self.copy() } } -unsafe impl NSFastEnumeration for NSArray { +unsafe impl NSFastEnumeration for NSArray { type Item = T; } -impl<'a, T: Message, O: Ownership> IntoIterator for &'a NSArray { +impl<'a, T: ?Sized + Message, O: Ownership> IntoIterator for &'a NSArray { type Item = &'a T; type IntoIter = NSFastEnumerator<'a, NSArray>; @@ -272,7 +272,7 @@ impl<'a, T: Message, O: Ownership> IntoIterator for &'a NSArray { } } -impl Index for NSArray { +impl Index for NSArray { type Output = T; fn index(&self, index: usize) -> &T { @@ -280,13 +280,13 @@ impl Index for NSArray { } } -impl IndexMut for NSArray { +impl IndexMut for NSArray { fn index_mut(&mut self, index: usize) -> &mut T { self.get_mut(index).unwrap() } } -impl DefaultId for NSArray { +impl DefaultId for NSArray { type Ownership = Shared; #[inline] @@ -295,7 +295,7 @@ impl DefaultId for NSArray { } } -impl fmt::Debug for NSArray { +impl fmt::Debug for NSArray { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.iter_fast()).finish() diff --git a/objc2/src/foundation/copying.rs b/objc2/src/foundation/copying.rs index af0996d00..6c39194be 100644 --- a/objc2/src/foundation/copying.rs +++ b/objc2/src/foundation/copying.rs @@ -28,7 +28,7 @@ pub unsafe trait NSCopying: Message { /// /// This is usually `Self`, but e.g. `NSMutableString` returns `NSString`. /// TODO: Verify??? - type Output: Message; + type Output: ?Sized + Message; fn copy(&self) -> Id { unsafe { msg_send_id![self, copy] } @@ -40,7 +40,7 @@ pub unsafe trait NSCopying: Message { /// Note that the `mutableCopy` selector must return an owned object! pub unsafe trait NSMutableCopying: Message { /// TODO - type Output: Message; + type Output: ?Sized + Message; fn mutable_copy(&self) -> Id { unsafe { msg_send_id![self, mutableCopy] } diff --git a/objc2/src/foundation/dictionary.rs b/objc2/src/foundation/dictionary.rs index 719eb6c1a..6c90cb62d 100644 --- a/objc2/src/foundation/dictionary.rs +++ b/objc2/src/foundation/dictionary.rs @@ -12,26 +12,38 @@ use crate::{ClassType, __inner_extern_class, extern_methods, msg_send, msg_send_ __inner_extern_class!( #[derive(PartialEq, Eq, Hash)] - pub struct NSDictionary { + pub struct NSDictionary { key: PhantomData>, obj: PhantomData>, } - unsafe impl ClassType for NSDictionary { + unsafe impl ClassType for NSDictionary { type Super = NSObject; } ); // TODO: SAFETY // Approximately same as `NSArray` -unsafe impl Sync for NSDictionary {} -unsafe impl Send for NSDictionary {} +unsafe impl Sync + for NSDictionary +{ +} +unsafe impl Send + for NSDictionary +{ +} // Approximately same as `NSArray` -impl UnwindSafe for NSDictionary {} -impl RefUnwindSafe for NSDictionary {} +impl UnwindSafe + for NSDictionary +{ +} +impl RefUnwindSafe + for NSDictionary +{ +} extern_methods!( - unsafe impl NSDictionary { + unsafe impl NSDictionary { pub fn new() -> Id { unsafe { msg_send_id![Self::class(), new] } } @@ -131,7 +143,7 @@ extern_methods!( } ); -impl DefaultId for NSDictionary { +impl DefaultId for NSDictionary { type Ownership = Shared; #[inline] @@ -140,11 +152,11 @@ impl DefaultId for NSDictionary { } } -unsafe impl NSFastEnumeration for NSDictionary { +unsafe impl NSFastEnumeration for NSDictionary { type Item = K; } -impl<'a, K: Message, V: Message> Index<&'a K> for NSDictionary { +impl<'a, K: ?Sized + Message, V: ?Sized + Message> Index<&'a K> for NSDictionary { type Output = V; fn index<'s>(&'s self, index: &'a K) -> &'s V { @@ -152,7 +164,9 @@ impl<'a, K: Message, V: Message> Index<&'a K> for NSDictionary { } } -impl fmt::Debug for NSDictionary { +impl fmt::Debug + for NSDictionary +{ #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let iter = self.iter_keys().zip(self.iter_values()); diff --git a/objc2/src/foundation/enumerator.rs b/objc2/src/foundation/enumerator.rs index 1d3629ec4..9af67a443 100644 --- a/objc2/src/foundation/enumerator.rs +++ b/objc2/src/foundation/enumerator.rs @@ -9,12 +9,12 @@ use crate::runtime::Object; use crate::{msg_send, Encode, Encoding, Message, RefEncode}; // TODO: https://doc.rust-lang.org/stable/reference/trait-bounds.html#lifetime-bounds -pub struct NSEnumerator<'a, T: Message> { +pub struct NSEnumerator<'a, T: ?Sized + Message> { id: Id, item: PhantomData<&'a T>, } -impl<'a, T: Message> NSEnumerator<'a, T> { +impl<'a, T: ?Sized + Message> NSEnumerator<'a, T> { /// TODO /// /// # Safety @@ -29,7 +29,7 @@ impl<'a, T: Message> NSEnumerator<'a, T> { } } -impl<'a, T: Message> Iterator for NSEnumerator<'a, T> { +impl<'a, T: ?Sized + Message> Iterator for NSEnumerator<'a, T> { type Item = &'a T; fn next(&mut self) -> Option<&'a T> { @@ -38,7 +38,7 @@ impl<'a, T: Message> Iterator for NSEnumerator<'a, T> { } pub unsafe trait NSFastEnumeration: Message { - type Item: Message; + type Item: ?Sized + Message; fn iter_fast(&self) -> NSFastEnumerator<'_, Self> { NSFastEnumerator::new(self) @@ -46,14 +46,14 @@ pub unsafe trait NSFastEnumeration: Message { } #[repr(C)] -struct NSFastEnumerationState { +struct NSFastEnumerationState { state: c_ulong, // TODO: Verify this is actually always 64 bit items_ptr: *const *const T, mutations_ptr: *mut c_ulong, extra: [c_ulong; 5], } -unsafe impl Encode for NSFastEnumerationState { +unsafe impl Encode for NSFastEnumerationState { const ENCODING: Encoding = Encoding::Struct( "?", &[ @@ -65,11 +65,11 @@ unsafe impl Encode for NSFastEnumerationState { ); } -unsafe impl RefEncode for NSFastEnumerationState { +unsafe impl RefEncode for NSFastEnumerationState { const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING); } -fn enumerate<'a, 'b: 'a, C: NSFastEnumeration + ?Sized>( +fn enumerate<'a, 'b: 'a, C: ?Sized + NSFastEnumeration>( object: &'b C, state: &mut NSFastEnumerationState, buf: &'a mut [*const C::Item], @@ -94,7 +94,7 @@ fn enumerate<'a, 'b: 'a, C: NSFastEnumeration + ?Sized>( const FAST_ENUM_BUF_SIZE: usize = 16; -pub struct NSFastEnumerator<'a, C: 'a + NSFastEnumeration + ?Sized> { +pub struct NSFastEnumerator<'a, C: 'a + ?Sized + NSFastEnumeration> { object: &'a C, ptr: *const *const C::Item, @@ -104,7 +104,7 @@ pub struct NSFastEnumerator<'a, C: 'a + NSFastEnumeration + ?Sized> { buf: [*const C::Item; FAST_ENUM_BUF_SIZE], } -impl<'a, C: NSFastEnumeration + ?Sized> NSFastEnumerator<'a, C> { +impl<'a, C: ?Sized + NSFastEnumeration> NSFastEnumerator<'a, C> { fn new(object: &'a C) -> Self { Self { object, @@ -149,7 +149,7 @@ impl<'a, C: NSFastEnumeration + ?Sized> NSFastEnumerator<'a, C> { } } -impl<'a, C: NSFastEnumeration + ?Sized> Iterator for NSFastEnumerator<'a, C> { +impl<'a, C: ?Sized + NSFastEnumeration> Iterator for NSFastEnumerator<'a, C> { type Item = &'a C::Item; fn next(&mut self) -> Option<&'a C::Item> { diff --git a/objc2/src/foundation/mutable_array.rs b/objc2/src/foundation/mutable_array.rs index 7cbd4eda5..c7df4eae8 100644 --- a/objc2/src/foundation/mutable_array.rs +++ b/objc2/src/foundation/mutable_array.rs @@ -11,7 +11,9 @@ use super::{ NSObject, }; use crate::rc::{DefaultId, Id, Owned, Ownership, Shared, SliceId}; -use crate::{ClassType, Message, __inner_extern_class, extern_methods, msg_send, msg_send_id}; +use crate::{ + ClassType, Message, Thin, __inner_extern_class, extern_methods, msg_send, msg_send_id, +}; __inner_extern_class!( /// A growable ordered collection of objects. @@ -21,11 +23,11 @@ __inner_extern_class!( /// /// [apple-doc]: https://developer.apple.com/documentation/foundation/nsmutablearray?language=objc #[derive(PartialEq, Eq, Hash)] - pub struct NSMutableArray { + pub struct NSMutableArray { p: PhantomData<*mut ()>, } - unsafe impl ClassType for NSMutableArray { + unsafe impl ClassType for NSMutableArray { #[inherits(NSObject)] type Super = NSArray; } @@ -34,14 +36,14 @@ __inner_extern_class!( // SAFETY: Same as NSArray // // Put here because rustdoc doesn't show these otherwise -unsafe impl Sync for NSMutableArray {} -unsafe impl Send for NSMutableArray {} -unsafe impl Sync for NSMutableArray {} -unsafe impl Send for NSMutableArray {} +unsafe impl Sync for NSMutableArray {} +unsafe impl Send for NSMutableArray {} +unsafe impl Sync for NSMutableArray {} +unsafe impl Send for NSMutableArray {} extern_methods!( /// Generic creation methods. - unsafe impl NSMutableArray { + unsafe impl NSMutableArray { pub fn new() -> Id { // SAFETY: Same as `NSArray::new`, except mutable arrays are always // unique. @@ -56,7 +58,7 @@ extern_methods!( } /// Creation methods that produce shared arrays. - unsafe impl NSMutableArray { + unsafe impl NSMutableArray { pub fn from_slice(slice: &[Id]) -> Id { // SAFETY: Same as `NSArray::from_slice`, except mutable arrays are // always unique. @@ -65,7 +67,7 @@ extern_methods!( } /// Generic accessor methods. - unsafe impl NSMutableArray { + unsafe impl NSMutableArray { #[doc(alias = "addObject:")] pub fn push(&mut self, obj: Id) { // SAFETY: The object is not nil @@ -139,7 +141,7 @@ extern_methods!( #[doc(alias = "sortUsingFunction:context:")] pub fn sort_by Ordering>(&mut self, compare: F) { // TODO: "C-unwind" - extern "C" fn compare_with_closure Ordering>( + extern "C" fn compare_with_closure Ordering>( obj1: &U, obj2: &U, context: *mut c_void, @@ -174,28 +176,28 @@ extern_methods!( // Copying only possible when ItemOwnership = Shared /// This is implemented as a shallow copy. -unsafe impl NSCopying for NSMutableArray { +unsafe impl NSCopying for NSMutableArray { type Ownership = Shared; type Output = NSArray; } /// This is implemented as a shallow copy. -unsafe impl NSMutableCopying for NSMutableArray { +unsafe impl NSMutableCopying for NSMutableArray { type Output = NSMutableArray; } -impl alloc::borrow::ToOwned for NSMutableArray { +impl alloc::borrow::ToOwned for NSMutableArray { type Owned = Id, Owned>; fn to_owned(&self) -> Self::Owned { self.mutable_copy() } } -unsafe impl NSFastEnumeration for NSMutableArray { +unsafe impl NSFastEnumeration for NSMutableArray { type Item = T; } -impl<'a, T: Message, O: Ownership> IntoIterator for &'a NSMutableArray { +impl<'a, T: ?Sized + Message, O: Ownership> IntoIterator for &'a NSMutableArray { type Item = &'a T; type IntoIter = NSFastEnumerator<'a, NSMutableArray>; @@ -204,14 +206,14 @@ impl<'a, T: Message, O: Ownership> IntoIterator for &'a NSMutableArray { } } -impl Extend> for NSMutableArray { +impl Extend> for NSMutableArray { fn extend>>(&mut self, iter: I) { let iterator = iter.into_iter(); iterator.for_each(move |item| self.push(item)); } } -impl Index for NSMutableArray { +impl Index for NSMutableArray { type Output = T; fn index(&self, index: usize) -> &T { @@ -219,13 +221,13 @@ impl Index for NSMutableArray { } } -impl IndexMut for NSMutableArray { +impl IndexMut for NSMutableArray { fn index_mut(&mut self, index: usize) -> &mut T { self.get_mut(index).unwrap() } } -impl DefaultId for NSMutableArray { +impl DefaultId for NSMutableArray { type Ownership = Owned; #[inline] @@ -234,7 +236,7 @@ impl DefaultId for NSMutableArray { } } -impl fmt::Debug for NSMutableArray { +impl fmt::Debug for NSMutableArray { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) diff --git a/objc2/src/foundation/mutable_dictionary.rs b/objc2/src/foundation/mutable_dictionary.rs index 1a000adce..64b31c8ed 100644 --- a/objc2/src/foundation/mutable_dictionary.rs +++ b/objc2/src/foundation/mutable_dictionary.rs @@ -17,30 +17,39 @@ __inner_extern_class!( /// /// [apple-doc]: https://developer.apple.com/documentation/foundation/nsmutabledictionary?language=objc #[derive(PartialEq, Eq, Hash)] - pub struct NSMutableDictionary { + pub struct NSMutableDictionary { key: PhantomData>, obj: PhantomData>, } - unsafe impl ClassType for NSMutableDictionary { + unsafe impl ClassType for NSMutableDictionary { #[inherits(NSObject)] type Super = NSDictionary; } ); // Same as `NSDictionary` -unsafe impl Sync for NSMutableDictionary {} -unsafe impl Send for NSMutableDictionary {} +unsafe impl Sync + for NSMutableDictionary +{ +} +unsafe impl Send + for NSMutableDictionary +{ +} // Same as `NSDictionary` -impl UnwindSafe for NSMutableDictionary {} -impl RefUnwindSafe +impl UnwindSafe + for NSMutableDictionary +{ +} +impl RefUnwindSafe for NSMutableDictionary { } extern_methods!( - unsafe impl NSMutableDictionary { + unsafe impl NSMutableDictionary { /// Creates an empty [`NSMutableDictionary`]. /// /// # Examples @@ -238,11 +247,13 @@ extern_methods!( } ); -unsafe impl NSFastEnumeration for NSMutableDictionary { +unsafe impl NSFastEnumeration + for NSMutableDictionary +{ type Item = K; } -impl<'a, K: Message, V: Message> Index<&'a K> for NSMutableDictionary { +impl<'a, K: ?Sized + Message, V: ?Sized + Message> Index<&'a K> for NSMutableDictionary { type Output = V; fn index<'s>(&'s self, index: &'a K) -> &'s V { @@ -250,13 +261,13 @@ impl<'a, K: Message, V: Message> Index<&'a K> for NSMutableDictionary { } } -impl<'a, K: Message, V: Message> IndexMut<&'a K> for NSMutableDictionary { +impl<'a, K: ?Sized + Message, V: ?Sized + Message> IndexMut<&'a K> for NSMutableDictionary { fn index_mut<'s>(&'s mut self, index: &'a K) -> &'s mut V { self.get_mut(index).unwrap() } } -impl DefaultId for NSMutableDictionary { +impl DefaultId for NSMutableDictionary { type Ownership = Owned; #[inline] @@ -265,7 +276,9 @@ impl DefaultId for NSMutableDictionary { } } -impl fmt::Debug for NSMutableDictionary { +impl fmt::Debug + for NSMutableDictionary +{ #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) diff --git a/objc2/src/foundation/mutable_set.rs b/objc2/src/foundation/mutable_set.rs index 2df2a161b..b868edcf7 100644 --- a/objc2/src/foundation/mutable_set.rs +++ b/objc2/src/foundation/mutable_set.rs @@ -15,24 +15,24 @@ __inner_extern_class!( /// /// [apple-doc]: https://developer.apple.com/documentation/foundation/nsmutableset?language=objc #[derive(PartialEq, Eq, Hash)] - pub struct NSMutableSet { + pub struct NSMutableSet { p: PhantomData<*mut ()>, } - unsafe impl ClassType for NSMutableSet { + unsafe impl ClassType for NSMutableSet { #[inherits(NSObject)] type Super = NSSet; } ); // SAFETY: Same as NSSet -unsafe impl Sync for NSMutableSet {} -unsafe impl Send for NSMutableSet {} -unsafe impl Sync for NSMutableSet {} -unsafe impl Send for NSMutableSet {} +unsafe impl Sync for NSMutableSet {} +unsafe impl Send for NSMutableSet {} +unsafe impl Sync for NSMutableSet {} +unsafe impl Send for NSMutableSet {} extern_methods!( - unsafe impl NSMutableSet { + unsafe impl NSMutableSet { /// Creates an empty [`NSMutableSet`]. /// /// # Examples @@ -112,7 +112,7 @@ extern_methods!( } } - unsafe impl NSMutableSet { + unsafe impl NSMutableSet { /// Creates an [`NSMutableSet`] from a slice. /// /// # Examples @@ -139,7 +139,7 @@ extern_methods!( // We're explicit about `T` being `PartialEq` for these methods because the // set compares the input value with elements in the set // For comparison: Rust's HashSet requires similar methods to be `Hash` + `Eq` - unsafe impl NSMutableSet { + unsafe impl NSMutableSet { #[sel(addObject:)] fn add_object(&mut self, value: &T); @@ -201,27 +201,27 @@ extern_methods!( } ); -unsafe impl NSCopying for NSMutableSet { +unsafe impl NSCopying for NSMutableSet { type Ownership = Shared; type Output = NSSet; } -unsafe impl NSMutableCopying for NSMutableSet { +unsafe impl NSMutableCopying for NSMutableSet { type Output = NSMutableSet; } -impl alloc::borrow::ToOwned for NSMutableSet { +impl alloc::borrow::ToOwned for NSMutableSet { type Owned = Id, Owned>; fn to_owned(&self) -> Self::Owned { self.mutable_copy() } } -unsafe impl NSFastEnumeration for NSMutableSet { +unsafe impl NSFastEnumeration for NSMutableSet { type Item = T; } -impl<'a, T: Message, O: Ownership> IntoIterator for &'a NSMutableSet { +impl<'a, T: ?Sized + Message, O: Ownership> IntoIterator for &'a NSMutableSet { type Item = &'a T; type IntoIter = NSFastEnumerator<'a, NSMutableSet>; @@ -230,7 +230,7 @@ impl<'a, T: Message, O: Ownership> IntoIterator for &'a NSMutableSet { } } -impl Extend> for NSMutableSet { +impl Extend> for NSMutableSet { fn extend>>(&mut self, iter: I) { for item in iter { self.insert(item); @@ -238,7 +238,7 @@ impl Extend> for NSMutableSet DefaultId for NSMutableSet { +impl DefaultId for NSMutableSet { type Ownership = Owned; #[inline] @@ -247,7 +247,7 @@ impl DefaultId for NSMutableSet { } } -impl fmt::Debug for NSMutableSet { +impl fmt::Debug for NSMutableSet { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) diff --git a/objc2/src/foundation/set.rs b/objc2/src/foundation/set.rs index f13f772df..8227bb161 100644 --- a/objc2/src/foundation/set.rs +++ b/objc2/src/foundation/set.rs @@ -18,29 +18,29 @@ __inner_extern_class!( /// /// [apple-doc]: https://developer.apple.com/documentation/foundation/nsset?language=objc #[derive(PartialEq, Eq, Hash)] - pub struct NSSet { + pub struct NSSet { item: PhantomData>, notunwindsafe: PhantomData<&'static mut ()>, } - unsafe impl ClassType for NSSet { + unsafe impl ClassType for NSSet { type Super = NSObject; } ); // SAFETY: Same as NSArray -unsafe impl Sync for NSSet {} -unsafe impl Send for NSSet {} -unsafe impl Sync for NSSet {} -unsafe impl Send for NSSet {} +unsafe impl Sync for NSSet {} +unsafe impl Send for NSSet {} +unsafe impl Sync for NSSet {} +unsafe impl Send for NSSet {} // SAFETY: Same as NSArray -impl RefUnwindSafe for NSSet {} -impl UnwindSafe for NSSet {} -impl UnwindSafe for NSSet {} +impl RefUnwindSafe for NSSet {} +impl UnwindSafe for NSSet {} +impl UnwindSafe for NSSet {} #[track_caller] -pub(crate) unsafe fn with_objects( +pub(crate) unsafe fn with_objects( cls: &Class, objects: &[&T], ) -> Id { @@ -54,7 +54,7 @@ pub(crate) unsafe fn with_objects } extern_methods!( - unsafe impl NSSet { + unsafe impl NSSet { /// Creates an empty [`NSSet`]. /// /// # Examples @@ -197,7 +197,7 @@ extern_methods!( } } - unsafe impl NSSet { + unsafe impl NSSet { /// Creates an [`NSSet`] from a slice. /// /// # Examples @@ -248,7 +248,7 @@ extern_methods!( // We're explicit about `T` being `PartialEq` for these methods because the // set compares the input value(s) with elements in the set // For comparison: Rust's HashSet requires similar methods to be `Hash` + `Eq` - unsafe impl NSSet { + unsafe impl NSSet { /// Returns `true` if the set contains a value. /// /// # Examples @@ -353,27 +353,27 @@ extern_methods!( } ); -unsafe impl NSCopying for NSSet { +unsafe impl NSCopying for NSSet { type Ownership = Shared; type Output = NSSet; } -unsafe impl NSMutableCopying for NSSet { +unsafe impl NSMutableCopying for NSSet { type Output = NSMutableSet; } -impl alloc::borrow::ToOwned for NSSet { +impl alloc::borrow::ToOwned for NSSet { type Owned = Id, Shared>; fn to_owned(&self) -> Self::Owned { self.copy() } } -unsafe impl NSFastEnumeration for NSSet { +unsafe impl NSFastEnumeration for NSSet { type Item = T; } -impl<'a, T: Message, O: Ownership> IntoIterator for &'a NSSet { +impl<'a, T: ?Sized + Message, O: Ownership> IntoIterator for &'a NSSet { type Item = &'a T; type IntoIter = NSFastEnumerator<'a, NSSet>; @@ -382,7 +382,7 @@ impl<'a, T: Message, O: Ownership> IntoIterator for &'a NSSet { } } -impl DefaultId for NSSet { +impl DefaultId for NSSet { type Ownership = Shared; #[inline] @@ -391,7 +391,7 @@ impl DefaultId for NSSet { } } -impl fmt::Debug for NSSet { +impl fmt::Debug for NSSet { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_set().entries(self.iter_fast()).finish() diff --git a/objc2/src/lib.rs b/objc2/src/lib.rs index 04476e583..0e66e1731 100644 --- a/objc2/src/lib.rs +++ b/objc2/src/lib.rs @@ -186,6 +186,8 @@ compile_error!("The `std` feature currently must be enabled."); extern crate alloc; extern crate std; +pub(crate) use core::marker::Sized as Thin; + // The example uses NSObject without doing the __gnustep_hack #[cfg(all(feature = "apple", doctest))] #[doc = include_str!("../README.md")] diff --git a/objc2/src/macros/extern_class.rs b/objc2/src/macros/extern_class.rs index cfe10aa12..21324eff5 100644 --- a/objc2/src/macros/extern_class.rs +++ b/objc2/src/macros/extern_class.rs @@ -231,11 +231,11 @@ macro_rules! __inner_extern_class { // TODO: Expose this variant in the `object` macro. ( $(#[$m:meta])* - $v:vis struct $name:ident<$($t_struct:ident $(: $b_struct:ident $(= $default:ty)?)?),*> { + $v:vis struct $name:ident<$($t_struct:ident $(: $(?$s_struct:ident + )? $b_struct:ident $(= $default:ty)?)?),*> { $($field_vis:vis $field:ident: $field_ty:ty,)* } - unsafe impl<$($t_for:ident $(: $b_for:ident)?),*> ClassType for $for:ty { + unsafe impl<$($t_for:ident $(: $(?$s_for:ident + )? $b_for:ident)?),*> ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+)])? type Super = $superclass:ty; } @@ -243,16 +243,16 @@ macro_rules! __inner_extern_class { $crate::__inner_extern_class! { @__inner $(#[$m])* - $v struct $name ($($t_struct $(: $b_struct $(= $default)?)?),*) { + $v struct $name ($($t_struct $(: $(?$s_struct + )? $b_struct $(= $default)?)?),*) { $($field_vis $field: $field_ty,)* } - unsafe impl ($($t_for $(: $b_for)?),*) for $for { + unsafe impl ($($t_for $(: $(?$s_for + )? $b_for)?),*) for $for { INHERITS = [$superclass, $($($inheritance_rest,)+)? $crate::runtime::Object]; } } - unsafe impl<$($t_for $(: $b_for)?),*> ClassType for $for { + unsafe impl<$($t_for $(: $(?$s_for + )? $b_for)?),*> ClassType for $for { type Super = $superclass; const NAME: &'static str = stringify!($name); diff --git a/objc2/src/macros/extern_methods.rs b/objc2/src/macros/extern_methods.rs index 8d5f5857d..9b4c1fb7f 100644 --- a/objc2/src/macros/extern_methods.rs +++ b/objc2/src/macros/extern_methods.rs @@ -181,14 +181,14 @@ macro_rules! extern_methods { ( $( $(#[$impl_m:meta])* - unsafe impl<$($t:ident $(: $b:ident $(+ $rest:ident)*)?),*> $type:ty { + unsafe impl<$($t:ident $(: $(?$sized:ident +)? $b:ident $(+ $rest:ident)*)?),*> $type:ty { $($methods:tt)* } )+ ) => { $( $(#[$impl_m])* - impl<$($t $(: $b $(+ $rest)*)?),*> $type { + impl<$($t $(: $(?$sized +)? $b $(+ $rest)*)?),*> $type { $crate::__inner_extern_methods! { @rewrite_methods $($methods)* diff --git a/objc2/src/message/mod.rs b/objc2/src/message/mod.rs index ca3b820d8..ff1eef014 100644 --- a/objc2/src/message/mod.rs +++ b/objc2/src/message/mod.rs @@ -5,7 +5,7 @@ use core::ptr::NonNull; use crate::encode::{Encode, EncodeArguments, EncodeConvert, RefEncode}; use crate::rc::{Id, Owned, Ownership}; use crate::runtime::{Class, Imp, Object, Sel}; -use crate::ClassType; +use crate::{ClassType, Thin}; #[cfg(feature = "catch-all")] #[track_caller] @@ -100,7 +100,7 @@ use self::platform::{send_super_unverified, send_unverified}; /// // /// // And `Id` can now be constructed. /// ``` -pub unsafe trait Message: RefEncode {} +pub unsafe trait Message: RefEncode + Thin {} unsafe impl Message for Object {} @@ -110,17 +110,17 @@ pub(crate) mod private { pub trait Sealed {} - impl Sealed for *const T {} - impl Sealed for *mut T {} - impl Sealed for NonNull {} + impl Sealed for *const T {} + impl Sealed for *mut T {} + impl Sealed for NonNull {} - impl<'a, T: Message + ?Sized> Sealed for &'a T {} - impl<'a, T: Message + ?Sized> Sealed for &'a mut T {} + impl<'a, T: ?Sized + Message> Sealed for &'a T {} + impl<'a, T: ?Sized + Message> Sealed for &'a mut T {} - impl<'a, T: Message + ?Sized, O: Ownership> Sealed for &'a Id {} - impl<'a, T: Message + ?Sized> Sealed for &'a mut Id {} + impl<'a, T: ?Sized + Message, O: Ownership> Sealed for &'a Id {} + impl<'a, T: ?Sized + Message> Sealed for &'a mut Id {} - impl Sealed for ManuallyDrop> {} + impl Sealed for ManuallyDrop> {} impl Sealed for *const Class {} impl<'a> Sealed for &'a Class {} @@ -144,7 +144,7 @@ pub(crate) mod private { /// issue if you know a use-case where this restrition should be lifted! pub unsafe trait MessageReceiver: private::Sealed + Sized { #[doc(hidden)] - type __Inner: ?Sized; + type __Inner: ?Sized + Thin; #[doc(hidden)] fn __as_raw_receiver(self) -> *mut Object; @@ -254,7 +254,7 @@ pub unsafe trait MessageReceiver: private::Sealed + Sized { // Note that we implement MessageReceiver for unsized types as well, this is // to support `extern type`s in the future, not because we want to allow DSTs. -unsafe impl MessageReceiver for *const T { +unsafe impl MessageReceiver for *const T { type __Inner = T; #[inline] @@ -263,7 +263,7 @@ unsafe impl MessageReceiver for *const T { } } -unsafe impl MessageReceiver for *mut T { +unsafe impl MessageReceiver for *mut T { type __Inner = T; #[inline] @@ -272,7 +272,7 @@ unsafe impl MessageReceiver for *mut T { } } -unsafe impl MessageReceiver for NonNull { +unsafe impl MessageReceiver for NonNull { type __Inner = T; #[inline] @@ -281,7 +281,7 @@ unsafe impl MessageReceiver for NonNull { } } -unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a T { +unsafe impl<'a, T: ?Sized + Message> MessageReceiver for &'a T { type __Inner = T; #[inline] @@ -291,7 +291,7 @@ unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a T { } } -unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut T { +unsafe impl<'a, T: ?Sized + Message> MessageReceiver for &'a mut T { type __Inner = T; #[inline] @@ -301,7 +301,7 @@ unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut T { } } -unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a Id { +unsafe impl<'a, T: ?Sized + Message, O: Ownership> MessageReceiver for &'a Id { type __Inner = T; #[inline] @@ -310,7 +310,7 @@ unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a Id MessageReceiver for &'a mut Id { +unsafe impl<'a, T: ?Sized + Message> MessageReceiver for &'a mut Id { type __Inner = T; #[inline] @@ -319,7 +319,7 @@ unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut Id { } } -unsafe impl MessageReceiver for ManuallyDrop> { +unsafe impl MessageReceiver for ManuallyDrop> { type __Inner = T; #[inline] diff --git a/objc2/src/rc/allocated.rs b/objc2/src/rc/allocated.rs index 163baceb3..925b18ba7 100644 --- a/objc2/src/rc/allocated.rs +++ b/objc2/src/rc/allocated.rs @@ -1,3 +1,5 @@ +use crate::Thin; + /// A marker type that can be used within [`Id`] to indicate that the object /// has been allocated but not initialized. /// @@ -10,6 +12,6 @@ /// [`Id`]: crate::rc::Id #[repr(transparent)] #[derive(Debug)] -pub struct Allocated(T); +pub struct Allocated(T); // Explicitly don't implement `Deref`, `Message` nor `RefEncode`! diff --git a/objc2/src/rc/id.rs b/objc2/src/rc/id.rs index 1f7e5155e..415f5e09b 100644 --- a/objc2/src/rc/id.rs +++ b/objc2/src/rc/id.rs @@ -9,7 +9,7 @@ use super::Allocated; use super::AutoreleasePool; use super::{Owned, Ownership, Shared}; use crate::ffi; -use crate::{ClassType, Message}; +use crate::{ClassType, Message, Thin}; /// An pointer for Objective-C reference counted objects. /// @@ -48,6 +48,7 @@ use crate::{ClassType, Message}; /// [`Box`]: alloc::boxed::Box /// [`Arc`]: alloc::sync::Arc /// +/// /// # Caveats /// /// If the inner type implements [`Drop`], that implementation will not be @@ -55,8 +56,6 @@ use crate::{ClassType, Message}; /// do so. If you need to run some code when the object is destroyed, /// implement the `dealloc` method instead. /// -/// This allows `?Sized` types `T`, but the intention is to only support when -/// `T` is an `extern type` (yet unstable). /// /// # Examples /// @@ -97,10 +96,13 @@ use crate::{ClassType, Message}; /// // Do something with `&T` here /// ``` #[repr(transparent)] -// TODO: Figure out if `Message` bound on `T` would be better here? -// TODO: Add `ptr::Thin` bound on `T` to allow for only extern types -// TODO: Consider changing the name of Id -> Retain -pub struct Id { +// Alternative names: +#[doc(alias = "Retain")] +#[doc(alias = "Retained")] +#[doc(alias = "Arc")] +#[doc(alias = "Box")] +// Note: We explicitly don't use `T: Message` here to support `T=Allocated`. +pub struct Id { /// A pointer to the contained object. The pointer is always retained. /// /// It is important that this is `NonNull`, since we want to dereference @@ -124,7 +126,7 @@ pub struct Id { notunwindsafe: PhantomData<&'static mut ()>, } -impl Id { +impl Id { #[inline] unsafe fn new_nonnull(ptr: NonNull) -> Self { Self { @@ -136,7 +138,7 @@ impl Id { } } -impl Id, O> { +impl Id, O> { #[inline] pub(crate) unsafe fn new_allocated(ptr: *mut T) -> Option { // SAFETY: Upheld by the caller @@ -157,7 +159,7 @@ impl Id, O> { } } -impl Id { +impl Id { /// Constructs an [`Id`] to an object that already has +1 retain count. /// /// This is useful when you have a retain count that has been handed off @@ -243,7 +245,7 @@ impl Id { } } -impl Id { +impl Id { /// Returns a raw mutable pointer to the object. /// /// The pointer is valid for at least as long as the `Id` is held. @@ -258,8 +260,7 @@ impl Id { } } -// TODO: Add ?Sized bound -impl Id { +impl Id { /// Convert the type of the given object to another. /// /// This is equivalent to a `cast` between two pointers. @@ -287,7 +288,7 @@ impl Id { /// Additionally, you must ensure that any safety invariants that the new /// type has are upheld. #[inline] - pub unsafe fn cast(this: Self) -> Id { + pub unsafe fn cast(this: Self) -> Id { let ptr = ManuallyDrop::new(this).ptr.cast(); // SAFETY: The object is forgotten, so we have +1 retain count. // @@ -564,8 +565,7 @@ impl Id { // } // } -// TODO: Add ?Sized bound -impl Id { +impl Id { /// Autoreleases the owned [`Id`], returning a mutable reference bound to /// the pool. /// @@ -617,8 +617,7 @@ impl Id { } } -// TODO: Add ?Sized bound -impl Id { +impl Id { /// Autoreleases the shared [`Id`], returning an aliased reference bound /// to the pool. /// @@ -635,7 +634,7 @@ impl Id { } } -impl Id +impl Id where T::Super: 'static, { @@ -650,7 +649,7 @@ where } } -impl From> for Id { +impl From> for Id { /// Convert an owned to a shared [`Id`], allowing it to be cloned. /// /// Same as [`Id::into_shared`]. @@ -660,8 +659,7 @@ impl From> for Id { } } -// TODO: Add ?Sized bound -impl Clone for Id { +impl Clone for Id { /// Makes a clone of the shared object. /// /// This increases the object's reference count. @@ -684,7 +682,7 @@ impl Clone for Id { /// borrowed data. /// /// [dropck_eyepatch]: https://doc.rust-lang.org/nightly/nomicon/dropck.html#an-escape-hatch -impl Drop for Id { +impl Drop for Id { /// Releases the retained object. /// /// The contained object's destructor (if it has one) is never run! @@ -710,7 +708,7 @@ impl Drop for Id { /// clone a `Id`, send it to another thread, and drop the clone /// last, making `dealloc` get called on the other thread, and violate /// `T: !Send`. -unsafe impl Send for Id {} +unsafe impl Send for Id {} /// The `Sync` implementation requires `T: Sync` because `&Id` give /// access to `&T`. @@ -718,17 +716,17 @@ unsafe impl Send for Id {} /// Additiontally, it requires `T: Send`, because if `T: !Send`, you could /// clone a `&Id` from another thread, and drop the clone last, /// making `dealloc` get called on the other thread, and violate `T: !Send`. -unsafe impl Sync for Id {} +unsafe impl Sync for Id {} /// `Id` are `Send` if `T` is `Send` because they give the same /// access as having a T directly. -unsafe impl Send for Id {} +unsafe impl Send for Id {} /// `Id` are `Sync` if `T` is `Sync` because they give the same /// access as having a `T` directly. -unsafe impl Sync for Id {} +unsafe impl Sync for Id {} -impl Deref for Id { +impl Deref for Id { type Target = T; /// Obtain an immutable reference to the object. @@ -740,7 +738,7 @@ impl Deref for Id { } } -impl DerefMut for Id { +impl DerefMut for Id { /// Obtain a mutable reference to the object. #[inline] fn deref_mut(&mut self) -> &mut T { @@ -751,7 +749,7 @@ impl DerefMut for Id { } } -impl fmt::Pointer for Id { +impl fmt::Pointer for Id { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Pointer::fmt(&self.ptr.as_ptr(), f) } @@ -761,15 +759,15 @@ impl fmt::Pointer for Id { // // See https://doc.rust-lang.org/1.54.0/src/alloc/boxed.rs.html#1652-1675 // and the `Arc` implementation. -impl Unpin for Id {} +impl Unpin for Id {} -impl RefUnwindSafe for Id {} +impl RefUnwindSafe for Id {} // Same as `Arc`. -impl UnwindSafe for Id {} +impl UnwindSafe for Id {} // Same as `Box`. -impl UnwindSafe for Id {} +impl UnwindSafe for Id {} #[cfg(test)] mod tests { diff --git a/objc2/src/rc/id_forwarding_impls.rs b/objc2/src/rc/id_forwarding_impls.rs index f08484251..0250c218a 100644 --- a/objc2/src/rc/id_forwarding_impls.rs +++ b/objc2/src/rc/id_forwarding_impls.rs @@ -21,8 +21,9 @@ use std::error::Error; use std::io; use super::{Id, Owned, Ownership}; +use crate::Thin; -impl PartialEq for Id { +impl PartialEq for Id { #[inline] fn eq(&self, other: &Self) -> bool { (**self).eq(&**other) @@ -35,9 +36,9 @@ impl PartialEq for Id { } } -impl Eq for Id {} +impl Eq for Id {} -impl PartialOrd for Id { +impl PartialOrd for Id { #[inline] fn partial_cmp(&self, other: &Self) -> Option { (**self).partial_cmp(&**other) @@ -60,20 +61,20 @@ impl PartialOrd for Id { } } -impl Ord for Id { +impl Ord for Id { #[inline] fn cmp(&self, other: &Self) -> Ordering { (**self).cmp(&**other) } } -impl hash::Hash for Id { +impl hash::Hash for Id { fn hash(&self, state: &mut H) { (**self).hash(state) } } -impl hash::Hasher for Id { +impl hash::Hasher for Id { fn finish(&self) -> u64 { (**self).finish() } @@ -118,19 +119,19 @@ impl hash::Hasher for Id { } } -impl fmt::Display for Id { +impl fmt::Display for Id { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } -impl fmt::Debug for Id { +impl fmt::Debug for Id { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } -impl Iterator for Id { +impl Iterator for Id { type Item = I::Item; fn next(&mut self) -> Option { (**self).next() @@ -143,7 +144,7 @@ impl Iterator for Id { } } -impl DoubleEndedIterator for Id { +impl DoubleEndedIterator for Id { fn next_back(&mut self) -> Option { (**self).next_back() } @@ -152,13 +153,13 @@ impl DoubleEndedIterator for Id { } } -impl ExactSizeIterator for Id { +impl ExactSizeIterator for Id { fn len(&self) -> usize { (**self).len() } } -impl FusedIterator for Id {} +impl FusedIterator for Id {} // TODO: Consider this impl // impl<'a, T, O: Ownership> IntoIterator for &'a Id @@ -173,37 +174,37 @@ impl FusedIterator for Id {} // } // } -impl borrow::Borrow for Id { +impl borrow::Borrow for Id { fn borrow(&self) -> &T { Deref::deref(self) } } -impl borrow::BorrowMut for Id { +impl borrow::BorrowMut for Id { fn borrow_mut(&mut self) -> &mut T { DerefMut::deref_mut(self) } } -impl AsRef for Id { +impl AsRef for Id { fn as_ref(&self) -> &T { Deref::deref(self) } } -impl AsMut for Id { +impl AsMut for Id { fn as_mut(&mut self) -> &mut T { DerefMut::deref_mut(self) } } -impl Error for Id { +impl Error for Id { fn source(&self) -> Option<&(dyn Error + 'static)> { (**self).source() } } -impl io::Read for Id { +impl io::Read for Id { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) @@ -230,7 +231,7 @@ impl io::Read for Id { } } -impl io::Write for Id { +impl io::Write for Id { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) @@ -257,7 +258,7 @@ impl io::Write for Id { } } -impl io::Seek for Id { +impl io::Seek for Id { #[inline] fn seek(&mut self, pos: io::SeekFrom) -> io::Result { (**self).seek(pos) @@ -269,7 +270,7 @@ impl io::Seek for Id { } } -impl io::BufRead for Id { +impl io::BufRead for Id { #[inline] fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() @@ -291,7 +292,7 @@ impl io::BufRead for Id { } } -impl Future for Id { +impl Future for Id { type Output = T::Output; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { diff --git a/objc2/src/rc/id_traits.rs b/objc2/src/rc/id_traits.rs index bbcc9abdc..22b5a79e1 100644 --- a/objc2/src/rc/id_traits.rs +++ b/objc2/src/rc/id_traits.rs @@ -1,12 +1,12 @@ //! Helper traits for Id. use super::{Id, Owned, Ownership}; -use crate::Message; +use crate::{Message, Thin}; /// Helper trait for functionality on slices containing [`Id`]s. pub trait SliceId { /// The type of the items in the slice. - type Item: ?Sized; + type Item: ?Sized + Thin; /// Convert a slice of [`Id`]s into a slice of references. fn as_slice_ref(&self) -> &[&Self::Item]; @@ -22,7 +22,7 @@ pub trait SliceIdMut: SliceId { fn as_mut_slice_mut(&mut self) -> &mut [&mut Self::Item]; } -impl SliceId for [Id] { +impl SliceId for [Id] { type Item = T; fn as_slice_ref(&self) -> &[&T] { @@ -40,7 +40,7 @@ impl SliceId for [Id] { } } -impl SliceIdMut for [Id] { +impl SliceIdMut for [Id] { fn as_mut_slice_mut(&mut self) -> &mut [&mut T] { let ptr = self as *mut Self as *mut [&mut T]; // SAFETY: Id and &mut T have the same memory layout, and the @@ -53,7 +53,7 @@ impl SliceIdMut for [Id] { /// Helper trait to implement [`Default`] on types whoose default value is an /// [`Id`]. // TODO: Maybe make this `unsafe` and provide a default implementation? -pub trait DefaultId { +pub trait DefaultId: Thin { /// Indicates whether the default value is mutable or immutable. type Ownership: Ownership; diff --git a/objc2/src/rc/weak_id.rs b/objc2/src/rc/weak_id.rs index 151e5c7ae..2ba99e961 100644 --- a/objc2/src/rc/weak_id.rs +++ b/objc2/src/rc/weak_id.rs @@ -7,7 +7,7 @@ use std::panic::{RefUnwindSafe, UnwindSafe}; use super::{Id, Shared}; use crate::ffi; -use crate::Message; +use crate::{Message, Thin}; /// A pointer type for a weak reference to an Objective-C reference counted /// object. @@ -15,7 +15,7 @@ use crate::Message; /// Allows breaking reference cycles and safely checking whether the object /// has been deallocated. #[repr(transparent)] -pub struct WeakId { +pub struct WeakId { /// We give the runtime the address to this box, so that it can modify it /// even if the `WeakId` is moved. /// @@ -34,7 +34,7 @@ pub struct WeakId { item: PhantomData>, } -impl WeakId { +impl WeakId { /// Construct a new [`WeakId`] referencing the given shared [`Id`]. #[doc(alias = "objc_initWeak")] #[inline] @@ -76,7 +76,7 @@ impl WeakId { // TODO: Add `autorelease(&self) -> Option<&T>` using `objc_loadWeak`? } -impl Drop for WeakId { +impl Drop for WeakId { /// Drops the `WeakId` pointer. #[doc(alias = "objc_destroyWeak")] #[inline] @@ -85,8 +85,7 @@ impl Drop for WeakId { } } -// TODO: Add ?Sized -impl Clone for WeakId { +impl Clone for WeakId { /// Makes a clone of the `WeakId` that points to the same object. #[doc(alias = "objc_copyWeak")] fn clone(&self) -> Self { @@ -99,8 +98,7 @@ impl Clone for WeakId { } } -// TODO: Add ?Sized -impl Default for WeakId { +impl Default for WeakId { /// Constructs a new `WeakId` that doesn't reference any object. /// /// Calling [`Self::load`] on the return value always gives [`None`]. @@ -112,35 +110,35 @@ impl Default for WeakId { } /// This implementation follows the same reasoning as `Id`. -unsafe impl Sync for WeakId {} +unsafe impl Sync for WeakId {} /// This implementation follows the same reasoning as `Id`. -unsafe impl Send for WeakId {} +unsafe impl Send for WeakId {} // Unsure about the Debug bound on T, see std::sync::Weak -impl fmt::Debug for WeakId { +impl fmt::Debug for WeakId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(WeakId)") } } // Underneath this is just a `Box` -impl Unpin for WeakId {} +impl Unpin for WeakId {} // Same as `Id`. -impl RefUnwindSafe for WeakId {} +impl RefUnwindSafe for WeakId {} // Same as `Id`. -impl UnwindSafe for WeakId {} +impl UnwindSafe for WeakId {} -impl From> for WeakId { +impl From> for WeakId { #[inline] fn from(obj: Id) -> Self { WeakId::new(&obj) } } -impl TryFrom> for Id { +impl TryFrom> for Id { type Error = (); fn try_from(weak: WeakId) -> Result { weak.load().ok_or(()) From 996f48b8680aa493f461fad31781a9bb386c7f5f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 1 Sep 2022 00:18:10 +0200 Subject: [PATCH 2/3] Add `unstable-extern-types` feature --- .github/workflows/ci.yml | 2 +- objc-sys/Cargo.toml | 15 +++++++++------ objc-sys/src/lib.rs | 19 +++++++++++++------ objc2/CHANGELOG.md | 2 ++ objc2/Cargo.toml | 23 ++++++++++++++--------- objc2/src/cache.rs | 13 +++++++------ objc2/src/foundation/array.rs | 2 ++ objc2/src/foundation/mutable_array.rs | 2 +- objc2/src/foundation/set.rs | 4 +++- objc2/src/lib.rs | 4 ++++ 10 files changed, 56 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82ab1236f..9253255a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,7 +153,7 @@ jobs: TESTARGS: ${{ matrix.dinghy && ' ' || '--no-fail-fast' }} ${{ matrix.test-args }} SOME_FEATURES: ${{ matrix.features || 'malloc,block,exception,foundation' }} FEATURES: ${{ matrix.features || 'malloc,block,exception,foundation,catch-all,verify_message,uuid' }} - UNSTABLE_FEATURES: ${{ matrix.unstable-features || 'unstable-autoreleasesafe,unstable-c-unwind' }} + UNSTABLE_FEATURES: ${{ matrix.unstable-features || 'unstable-autoreleasesafe,unstable-c-unwind,unstable-extern-types' }} CMD: cargo runs-on: ${{ matrix.os }} diff --git a/objc-sys/Cargo.toml b/objc-sys/Cargo.toml index 16031dc64..1c5d6ad38 100644 --- a/objc-sys/Cargo.toml +++ b/objc-sys/Cargo.toml @@ -33,26 +33,29 @@ default = ["std", "apple"] std = ["alloc"] alloc = [] -# Link to Apple's objc4 +# Link to Apple's objc4. apple = [] -# Link to GNUStep's libobjc2 +# Link to GNUStep's libobjc2. gnustep-1-7 = [] gnustep-1-8 = ["gnustep-1-7"] gnustep-1-9 = ["gnustep-1-8"] gnustep-2-0 = ["gnustep-1-9"] gnustep-2-1 = ["gnustep-2-0"] -# Link to Microsoft's libobjc2 +# Link to Microsoft's libobjc2. unstable-winobjc = ["gnustep-1-8"] -# Link to ObjFW +# Link to ObjFW. unstable-objfw = [] -# Use nightly c_unwind feature +# Use nightly c_unwind feature. unstable-c-unwind = [] -# Private +# Use nightly extern_types feature to mark opaque types as !Sized. +unstable-extern-types = [] + +# Private. unstable-exception = ["cc"] unstable-docsrs = [] diff --git a/objc-sys/src/lib.rs b/objc-sys/src/lib.rs index a018e1ff8..dc2451c1d 100644 --- a/objc-sys/src/lib.rs +++ b/objc-sys/src/lib.rs @@ -28,6 +28,7 @@ #![cfg_attr(feature = "unstable-c-unwind", feature(c_unwind))] #![cfg_attr(feature = "unstable-docsrs", feature(doc_auto_cfg, doc_cfg_hide))] #![cfg_attr(feature = "unstable-docsrs", doc(cfg_hide(doc)))] +#![cfg_attr(feature = "unstable-extern-types", feature(extern_types))] // TODO: Remove this and add "no-std" category to Cargo.toml // Requires a better solution for C-types in `no_std` crates. @@ -41,9 +42,6 @@ compile_error!("The `std` feature currently must be enabled."); #[doc = include_str!("../README.md")] extern "C" {} -use core::cell::UnsafeCell; -use core::marker::{PhantomData, PhantomPinned}; - macro_rules! generate_linking_tests { { extern $abi:literal {$( @@ -170,9 +168,18 @@ pub use various::*; /// /// Downstream libraries can always manually opt in to these types afterwards. /// (It's also less of a breaking change on our part if we re-add these). -/// -/// TODO: Replace this with `extern type` to also mark it as `!Sized`. -type OpaqueData = UnsafeCell, PhantomPinned)>>; +#[cfg(not(feature = "unstable-extern-types"))] +type OpaqueData = core::cell::UnsafeCell< + core::marker::PhantomData<( + *const core::cell::UnsafeCell<()>, + core::marker::PhantomPinned, + )>, +>; + +#[cfg(feature = "unstable-extern-types")] +extern "C" { + type OpaqueData; +} #[cfg(test)] mod tests { diff --git a/objc2/CHANGELOG.md b/objc2/CHANGELOG.md index 44f5428c7..a089422a7 100644 --- a/objc2/CHANGELOG.md +++ b/objc2/CHANGELOG.md @@ -16,6 +16,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * **BREAKING**: Added required `ClassType::NAME` constant for statically determining the name of a specific class. * Allow directly specifying class name in declare_class! macro. +* Added the `"unstable-extern-types"` feature flags to make relevant types + `!Sized`. ### Changed * **BREAKING**: Slightly changed when a type implements `?Sized` to support diff --git a/objc2/Cargo.toml b/objc2/Cargo.toml index 0c88a5ffe..5226d0a65 100644 --- a/objc2/Cargo.toml +++ b/objc2/Cargo.toml @@ -47,6 +47,14 @@ malloc = ["malloc_buf"] # Expose features that requires creating blocks. block = ["block2"] +# Runtime selection. See `objc-sys` for details. +apple = ["objc-sys/apple", "objc2-encode/apple", "block2?/apple"] +gnustep-1-7 = ["objc-sys/gnustep-1-7", "objc2-encode/gnustep-1-7", "block2?/gnustep-1-7"] +gnustep-1-8 = ["gnustep-1-7", "objc-sys/gnustep-1-8", "objc2-encode/gnustep-1-8", "block2?/gnustep-1-8"] +gnustep-1-9 = ["gnustep-1-8", "objc-sys/gnustep-1-9", "objc2-encode/gnustep-1-9", "block2?/gnustep-1-9"] +gnustep-2-0 = ["gnustep-1-9", "objc-sys/gnustep-2-0", "objc2-encode/gnustep-2-0", "block2?/gnustep-2-0"] +gnustep-2-1 = ["gnustep-2-0", "objc-sys/gnustep-2-1", "objc2-encode/gnustep-2-1", "block2?/gnustep-2-1"] + # Make the `sel!` macro look up the selector statically. # # The plan is to enable this by default, but right now we are uncertain of @@ -69,16 +77,13 @@ unstable-autoreleasesafe = [] # `objc2-encode/unstable-c-unwind` to use this. unstable-c-unwind = [] -# For better documentation on docs.rs -unstable-docsrs = [] +# Use nightly features to make Object and other types !Sized. +# +# You must manually enable `objc-sys/unstable-extern-types` to use this. +unstable-extern-types = [] -# Runtime selection. See `objc-sys` for details. -apple = ["objc-sys/apple", "objc2-encode/apple", "block2?/apple"] -gnustep-1-7 = ["objc-sys/gnustep-1-7", "objc2-encode/gnustep-1-7", "block2?/gnustep-1-7"] -gnustep-1-8 = ["gnustep-1-7", "objc-sys/gnustep-1-8", "objc2-encode/gnustep-1-8", "block2?/gnustep-1-8"] -gnustep-1-9 = ["gnustep-1-8", "objc-sys/gnustep-1-9", "objc2-encode/gnustep-1-9", "block2?/gnustep-1-9"] -gnustep-2-0 = ["gnustep-1-9", "objc-sys/gnustep-2-0", "objc2-encode/gnustep-2-0", "block2?/gnustep-2-0"] -gnustep-2-1 = ["gnustep-2-0", "objc-sys/gnustep-2-1", "objc2-encode/gnustep-2-1", "block2?/gnustep-2-1"] +# Private. +unstable-docsrs = [] [dependencies] malloc_buf = { version = "1.0", optional = true } diff --git a/objc2/src/cache.rs b/objc2/src/cache.rs index 28b32c0b2..28df2c885 100644 --- a/objc2/src/cache.rs +++ b/objc2/src/cache.rs @@ -1,3 +1,4 @@ +use core::ffi::c_void; use core::ptr; use core::sync::atomic::{AtomicPtr, Ordering}; @@ -7,7 +8,7 @@ use crate::runtime::{Class, Sel}; /// Allows storing a [`Sel`] in a static and lazily loading it. #[doc(hidden)] pub struct CachedSel { - ptr: AtomicPtr, + ptr: AtomicPtr, } impl CachedSel { @@ -24,7 +25,7 @@ impl CachedSel { #[doc(hidden)] pub unsafe fn get(&self, name: &str) -> Sel { // `Relaxed` should be fine since `sel_registerName` is thread-safe. - let ptr = self.ptr.load(Ordering::Relaxed); + let ptr: *const ffi::objc_selector = self.ptr.load(Ordering::Relaxed).cast(); unsafe { Sel::from_ptr(ptr) }.unwrap_or_else(|| { // The panic inside `Sel::register_unchecked` is unfortunate, but // strict correctness is more important than speed @@ -34,7 +35,7 @@ impl CachedSel { // We know this, because we construct it in `sel!` ourselves let sel = unsafe { Sel::register_unchecked(name.as_ptr().cast()) }; self.ptr - .store(sel.as_ptr() as *mut ffi::objc_selector, Ordering::Relaxed); + .store(sel.as_ptr() as *mut c_void, Ordering::Relaxed); sel }) } @@ -43,7 +44,7 @@ impl CachedSel { /// Allows storing a [`Class`] reference in a static and lazily loading it. #[doc(hidden)] pub struct CachedClass { - ptr: AtomicPtr, + ptr: AtomicPtr, } impl CachedClass { @@ -60,12 +61,12 @@ impl CachedClass { #[doc(hidden)] pub unsafe fn get(&self, name: &str) -> Option<&'static Class> { // `Relaxed` should be fine since `objc_getClass` is thread-safe. - let ptr = self.ptr.load(Ordering::Relaxed); + let ptr: *const Class = self.ptr.load(Ordering::Relaxed).cast(); if let Some(cls) = unsafe { ptr.as_ref() } { Some(cls) } else { let ptr: *const Class = unsafe { ffi::objc_getClass(name.as_ptr().cast()) }.cast(); - self.ptr.store(ptr as *mut Class, Ordering::Relaxed); + self.ptr.store(ptr as *mut c_void, Ordering::Relaxed); unsafe { ptr.as_ref() } } } diff --git a/objc2/src/foundation/array.rs b/objc2/src/foundation/array.rs index 3bc5f05f6..07d017f87 100644 --- a/objc2/src/foundation/array.rs +++ b/objc2/src/foundation/array.rs @@ -63,6 +63,8 @@ __inner_extern_class!( ); // SAFETY: Same as Id (which is what NSArray effectively stores). +// +// Duplicated here, rustdoc doesn't show these otherwise. unsafe impl Sync for NSArray {} unsafe impl Send for NSArray {} unsafe impl Sync for NSArray {} diff --git a/objc2/src/foundation/mutable_array.rs b/objc2/src/foundation/mutable_array.rs index c7df4eae8..e9fcf860f 100644 --- a/objc2/src/foundation/mutable_array.rs +++ b/objc2/src/foundation/mutable_array.rs @@ -35,7 +35,7 @@ __inner_extern_class!( // SAFETY: Same as NSArray // -// Put here because rustdoc doesn't show these otherwise +// Duplicated here, rustdoc doesn't show these otherwise. unsafe impl Sync for NSMutableArray {} unsafe impl Send for NSMutableArray {} unsafe impl Sync for NSMutableArray {} diff --git a/objc2/src/foundation/set.rs b/objc2/src/foundation/set.rs index 8227bb161..49d82f660 100644 --- a/objc2/src/foundation/set.rs +++ b/objc2/src/foundation/set.rs @@ -28,7 +28,9 @@ __inner_extern_class!( } ); -// SAFETY: Same as NSArray +// SAFETY: Same as Id. +// +// Duplicated here, rustdoc doesn't show these otherwise. unsafe impl Sync for NSSet {} unsafe impl Send for NSSet {} unsafe impl Sync for NSSet {} diff --git a/objc2/src/lib.rs b/objc2/src/lib.rs index 0e66e1731..fb8c44ada 100644 --- a/objc2/src/lib.rs +++ b/objc2/src/lib.rs @@ -167,6 +167,7 @@ )] #![cfg_attr(feature = "unstable-c-unwind", feature(c_unwind))] #![cfg_attr(feature = "unstable-docsrs", feature(doc_auto_cfg))] +#![cfg_attr(feature = "unstable-extern-types", feature(extern_types, ptr_metadata))] #![warn(elided_lifetimes_in_paths)] #![warn(missing_docs)] #![deny(non_ascii_idents)] @@ -186,7 +187,10 @@ compile_error!("The `std` feature currently must be enabled."); extern crate alloc; extern crate std; +#[cfg(not(feature = "unstable-extern-types"))] pub(crate) use core::marker::Sized as Thin; +#[cfg(feature = "unstable-extern-types")] +pub(crate) use core::ptr::Thin; // The example uses NSObject without doing the __gnustep_hack #[cfg(all(feature = "apple", doctest))] From d285c2a23829cf0dd7bd92f2004e1af9865e108c Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 1 Sep 2022 01:11:05 +0200 Subject: [PATCH 3/3] TMP --- objc2/src/__macro_helpers.rs | 10 ++++++++-- objc2/src/foundation/array.rs | 11 ++++++++--- objc2/src/foundation/set.rs | 11 ++++++++--- objc2/src/rc/id.rs | 5 ++++- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/objc2/src/__macro_helpers.rs b/objc2/src/__macro_helpers.rs index e6a3fa473..29e077d89 100644 --- a/objc2/src/__macro_helpers.rs +++ b/objc2/src/__macro_helpers.rs @@ -107,7 +107,10 @@ impl MsgSendId<&'_ Class, T, O> for New { } } -impl MsgSendId<&'_ Class, Allocated, O> for Alloc { +impl MsgSendId<&'_ Class, Allocated, O> for Alloc +where + Allocated: Thin, +{ #[inline] #[track_caller] unsafe fn send_message_id, O>>( @@ -123,7 +126,10 @@ impl MsgSendId<&'_ Class, Allocated, O> fo } } -impl MsgSendId, O>>, T, O> for Init { +impl MsgSendId, O>>, T, O> for Init +where + Allocated: Thin, +{ #[inline] #[track_caller] unsafe fn send_message_id>( diff --git a/objc2/src/foundation/array.rs b/objc2/src/foundation/array.rs index 07d017f87..440c47a4f 100644 --- a/objc2/src/foundation/array.rs +++ b/objc2/src/foundation/array.rs @@ -8,9 +8,11 @@ use super::{ NSCopying, NSEnumerator, NSFastEnumeration, NSFastEnumerator, NSMutableArray, NSMutableCopying, NSObject, NSRange, }; -use crate::rc::{DefaultId, Id, Owned, Ownership, Shared, SliceId}; +use crate::rc::{Allocated, DefaultId, Id, Owned, Ownership, Shared, SliceId}; use crate::runtime::{Class, Object}; -use crate::{ClassType, Message, __inner_extern_class, extern_methods, msg_send, msg_send_id}; +use crate::{ + ClassType, Message, Thin, __inner_extern_class, extern_methods, msg_send, msg_send_id, +}; __inner_extern_class!( /// An immutable ordered collection of objects. @@ -79,7 +81,10 @@ impl UnwindSafe for NSArray {} pub(crate) unsafe fn with_objects( cls: &Class, objects: &[&T], -) -> Id { +) -> Id +where + Allocated: Thin, +{ unsafe { msg_send_id![ msg_send_id![cls, alloc], diff --git a/objc2/src/foundation/set.rs b/objc2/src/foundation/set.rs index 49d82f660..47be45936 100644 --- a/objc2/src/foundation/set.rs +++ b/objc2/src/foundation/set.rs @@ -7,9 +7,11 @@ use super::{ NSArray, NSCopying, NSEnumerator, NSFastEnumeration, NSFastEnumerator, NSMutableCopying, NSMutableSet, NSObject, }; -use crate::rc::{DefaultId, Id, Owned, Ownership, Shared, SliceId}; +use crate::rc::{Allocated, DefaultId, Id, Owned, Ownership, Shared, SliceId}; use crate::runtime::Class; -use crate::{ClassType, Message, __inner_extern_class, extern_methods, msg_send, msg_send_id}; +use crate::{ + ClassType, Message, Thin, __inner_extern_class, extern_methods, msg_send, msg_send_id, +}; __inner_extern_class!( /// An immutable unordered collection of unique objects. @@ -45,7 +47,10 @@ impl UnwindSafe for NSSet {} pub(crate) unsafe fn with_objects( cls: &Class, objects: &[&T], -) -> Id { +) -> Id +where + Allocated: Thin, +{ unsafe { msg_send_id![ msg_send_id![cls, alloc], diff --git a/objc2/src/rc/id.rs b/objc2/src/rc/id.rs index 415f5e09b..b430edb10 100644 --- a/objc2/src/rc/id.rs +++ b/objc2/src/rc/id.rs @@ -138,7 +138,10 @@ impl Id { } } -impl Id, O> { +impl Id, O> +where + Allocated: Thin, +{ #[inline] pub(crate) unsafe fn new_allocated(ptr: *mut T) -> Option { // SAFETY: Upheld by the caller