Skip to content

Commit

Permalink
Relax ProtocolType requirement on ProtocolObject
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Sep 21, 2023
1 parent 3320f39 commit 076a745
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 33 deletions.
2 changes: 1 addition & 1 deletion crates/objc2/src/macros/extern_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ macro_rules! __inner_extern_protocol {
$(#[$impl_m])*
unsafe impl<T> $name for $crate::runtime::ProtocolObject<T>
where
T: ?$crate::__macro_helpers::Sized + $crate::ProtocolType + $name
T: ?$crate::__macro_helpers::Sized + $name
{}

// SAFETY: The specified name is ensured by caller to be a protocol,
Expand Down
23 changes: 10 additions & 13 deletions crates/objc2/src/mutability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
use core::marker::PhantomData;

use crate::runtime::{AnyObject, ProtocolObject};
use crate::{ClassType, Message, ProtocolType};
use crate::{ClassType, Message};

mod private_mutability {
pub trait Sealed {}
Expand Down Expand Up @@ -269,7 +269,7 @@ mod private_traits {
}

impl<T: ?Sized + ClassType> private_traits::Sealed for T {}
impl<P: ?Sized + ProtocolType> private_traits::Sealed for ProtocolObject<P> {}
impl<P: ?Sized> private_traits::Sealed for ProtocolObject<P> {}
impl private_traits::Sealed for AnyObject {}

/// Marker trait for classes where [`Id::clone`] is safe.
Expand Down Expand Up @@ -303,7 +303,7 @@ impl MutabilityIsIdCloneable for InteriorMutable {}
impl MutabilityIsIdCloneable for MainThreadOnly {}

unsafe impl<T: ?Sized + ClassType> IsIdCloneable for T where T::Mutability: MutabilityIsIdCloneable {}
unsafe impl<P: ?Sized + ProtocolType + IsIdCloneable> IsIdCloneable for ProtocolObject<P> {}
unsafe impl<P: ?Sized + IsIdCloneable> IsIdCloneable for ProtocolObject<P> {}
// SAFETY: Same as for root classes.
unsafe impl IsIdCloneable for AnyObject {}

Expand Down Expand Up @@ -336,7 +336,7 @@ impl MutabilityIsRetainable for InteriorMutable {}
impl MutabilityIsRetainable for MainThreadOnly {}

unsafe impl<T: ?Sized + ClassType> IsRetainable for T where T::Mutability: MutabilityIsRetainable {}
unsafe impl<P: ?Sized + ProtocolType + IsRetainable> IsRetainable for ProtocolObject<P> {}
unsafe impl<P: ?Sized + IsRetainable> IsRetainable for ProtocolObject<P> {}

/// Marker trait for classes that can be allocated from any thread.
///
Expand Down Expand Up @@ -367,10 +367,7 @@ unsafe impl<T: ?Sized + ClassType> IsAllocableAnyThread for T where
T::Mutability: MutabilityIsAllocableAnyThread
{
}
unsafe impl<P: ?Sized + ProtocolType + IsAllocableAnyThread> IsAllocableAnyThread
for ProtocolObject<P>
{
}
unsafe impl<P: ?Sized + IsAllocableAnyThread> IsAllocableAnyThread for ProtocolObject<P> {}

/// Marker trait for classes that may feasibly be used behind a mutable
/// reference.
Expand Down Expand Up @@ -401,7 +398,7 @@ unsafe impl<T: ?Sized + ClassType> IsAllowedMutable for T where
T::Mutability: MutabilityIsAllowedMutable
{
}
unsafe impl<P: ?Sized + ProtocolType + IsAllowedMutable> IsAllowedMutable for ProtocolObject<P> {}
unsafe impl<P: ?Sized + IsAllowedMutable> IsAllowedMutable for ProtocolObject<P> {}
// SAFETY: Same as for root classes.
unsafe impl IsAllowedMutable for AnyObject {}

Expand Down Expand Up @@ -430,7 +427,7 @@ impl MutabilityIsMutable for Mutable {}
impl<IS: ?Sized> MutabilityIsMutable for MutableWithImmutableSuperclass<IS> {}

unsafe impl<T: ?Sized + ClassType> IsMutable for T where T::Mutability: MutabilityIsMutable {}
unsafe impl<P: ?Sized + ProtocolType + IsMutable> IsMutable for ProtocolObject<P> {}
unsafe impl<P: ?Sized + IsMutable> IsMutable for ProtocolObject<P> {}

/// Marker trait for classes that are only available on the main thread.
///
Expand All @@ -455,7 +452,7 @@ unsafe impl<T: ?Sized + ClassType> IsMainThreadOnly for T where
T::Mutability: MutabilityIsMainThreadOnly
{
}
unsafe impl<P: ?Sized + ProtocolType + IsMainThreadOnly> IsMainThreadOnly for ProtocolObject<P> {}
unsafe impl<P: ?Sized + IsMainThreadOnly> IsMainThreadOnly for ProtocolObject<P> {}

/// Marker trait for classes whose `hash` and `isEqual:` methods are stable.
///
Expand Down Expand Up @@ -489,7 +486,7 @@ impl<MS: ?Sized> MutabilityHashIsStable for ImmutableWithMutableSubclass<MS> {}
impl<IS: ?Sized> MutabilityHashIsStable for MutableWithImmutableSuperclass<IS> {}

unsafe impl<T: ?Sized + ClassType> HasStableHash for T where T::Mutability: MutabilityHashIsStable {}
unsafe impl<P: ?Sized + ProtocolType + HasStableHash> HasStableHash for ProtocolObject<P> {}
unsafe impl<P: ?Sized + HasStableHash> HasStableHash for ProtocolObject<P> {}

/// Retrieve the immutable/mutable counterpart class, and fall back to `Self`
/// if not applicable.
Expand Down Expand Up @@ -589,7 +586,7 @@ where
type Mutable = <T::Mutability as private_counterpart::MutabilityCounterpartOrSelf<T>>::Mutable;
}

unsafe impl<P: ?Sized + ProtocolType> CounterpartOrSelf for ProtocolObject<P> {
unsafe impl<P: ?Sized> CounterpartOrSelf for ProtocolObject<P> {
// SAFETY: The only place where this would differ from `Self` is for
// classes with `MutableWithImmutableSuperclass<IS>`.
//
Expand Down
36 changes: 17 additions & 19 deletions crates/objc2/src/runtime/protocol_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::encode::{Encoding, RefEncode};
use crate::rc::{autoreleasepool_leaking, Id};
use crate::runtime::__nsstring::nsstring_to_str;
use crate::runtime::{AnyObject, NSObjectProtocol};
use crate::{Message, ProtocolType};
use crate::Message;

/// An internal helper trait for [`ProtocolObject`].
///
Expand Down Expand Up @@ -57,25 +57,25 @@ pub unsafe trait ImplementedBy<T: ?Sized + Message> {
/// ```
#[doc(alias = "id")]
#[repr(C)]
pub struct ProtocolObject<P: ?Sized + ProtocolType> {
pub struct ProtocolObject<P: ?Sized> {
inner: AnyObject,
p: PhantomData<P>,
}

// SAFETY: The type is `#[repr(C)]` and `AnyObject` internally
unsafe impl<P: ?Sized + ProtocolType> RefEncode for ProtocolObject<P> {
unsafe impl<P: ?Sized> RefEncode for ProtocolObject<P> {
const ENCODING_REF: Encoding = Encoding::Object;
}

// SAFETY: The type is `AnyObject` internally, and is mean to be messaged
// as-if it's an object.
unsafe impl<P: ?Sized + ProtocolType> Message for ProtocolObject<P> {}
unsafe impl<P: ?Sized> Message for ProtocolObject<P> {}

impl<P: ?Sized + ProtocolType> ProtocolObject<P> {
impl<P: ?Sized> ProtocolObject<P> {
/// Get an immutable type-erased reference from a type implementing a
/// protocol.
#[inline]
pub fn from_ref<T: Message>(obj: &T) -> &Self
pub fn from_ref<T: ?Sized + Message>(obj: &T) -> &Self
where
P: ImplementedBy<T>,
{
Expand All @@ -89,7 +89,7 @@ impl<P: ?Sized + ProtocolType> ProtocolObject<P> {
/// Get a mutable type-erased reference from a type implementing a
/// protocol.
#[inline]
pub fn from_mut<T: Message>(obj: &mut T) -> &mut Self
pub fn from_mut<T: ?Sized + Message>(obj: &mut T) -> &mut Self
where
P: ImplementedBy<T>,
{
Expand Down Expand Up @@ -118,24 +118,24 @@ impl<P: ?Sized + ProtocolType> ProtocolObject<P> {
}
}

impl<P: ?Sized + ProtocolType + NSObjectProtocol> PartialEq for ProtocolObject<P> {
impl<P: ?Sized + NSObjectProtocol> PartialEq for ProtocolObject<P> {
#[inline]
#[doc(alias = "isEqual:")]
fn eq(&self, other: &Self) -> bool {
self.__isEqual(other)
}
}

impl<P: ?Sized + ProtocolType + NSObjectProtocol> Eq for ProtocolObject<P> {}
impl<P: ?Sized + NSObjectProtocol> Eq for ProtocolObject<P> {}

impl<P: ?Sized + ProtocolType + NSObjectProtocol> hash::Hash for ProtocolObject<P> {
impl<P: ?Sized + NSObjectProtocol> hash::Hash for ProtocolObject<P> {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.__hash().hash(state);
}
}

impl<P: ?Sized + ProtocolType + NSObjectProtocol> fmt::Debug for ProtocolObject<P> {
impl<P: ?Sized + NSObjectProtocol> fmt::Debug for ProtocolObject<P> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Attempt to format description string
if let Some(description) = self.__description() {
Expand All @@ -159,29 +159,27 @@ impl<P: ?Sized + ProtocolType + NSObjectProtocol> fmt::Debug for ProtocolObject<
}
}

impl<P, T> AsRef<ProtocolObject<T>> for ProtocolObject<P>
impl<P: ?Sized, T> AsRef<ProtocolObject<T>> for ProtocolObject<P>
where
P: ?Sized + ProtocolType,
T: ?Sized + ProtocolType + ImplementedBy<ProtocolObject<P>>,
T: ?Sized + ImplementedBy<ProtocolObject<P>>,
{
#[inline]
fn as_ref(&self) -> &ProtocolObject<T> {
ProtocolObject::from_ref(self)
}
}

impl<P, T> AsMut<ProtocolObject<T>> for ProtocolObject<P>
impl<P: ?Sized, T> AsMut<ProtocolObject<T>> for ProtocolObject<P>
where
P: ?Sized + ProtocolType,
T: ?Sized + ProtocolType + ImplementedBy<ProtocolObject<P>>,
T: ?Sized + ImplementedBy<ProtocolObject<P>>,
{
#[inline]
fn as_mut(&mut self) -> &mut ProtocolObject<T> {
ProtocolObject::from_mut(self)
}
}

// TODO: Maybe iplement Borrow + BorrowMut?
// TODO: Maybe implement Borrow + BorrowMut?

#[cfg(test)]
#[allow(clippy::missing_safety_doc)]
Expand All @@ -194,7 +192,7 @@ mod tests {
use super::*;
use crate::mutability::Mutable;
use crate::runtime::{NSObject, NSObjectProtocol};
use crate::{declare_class, extern_methods, extern_protocol, ClassType};
use crate::{declare_class, extern_methods, extern_protocol, ClassType, ProtocolType};

extern_protocol!(
unsafe trait Foo {
Expand Down

0 comments on commit 076a745

Please sign in to comment.