Skip to content

Commit 18df32f

Browse files
committed
Relax ProtocolType requirement on ProtocolObject
This allows us to do `ProtocolObject<dyn ProtocolA + ProtocolB>` in the future.
1 parent e92d67a commit 18df32f

File tree

6 files changed

+274
-33
lines changed

6 files changed

+274
-33
lines changed

crates/objc2/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
149149
* **BREAKING**: Make `rc::Allocated` allowed to be `NULL` internally, such
150150
that uses of `Option<Allocated<T>>` is now simply `Allocated<T>`.
151151
* `AnyObject::class` now returns a `'static` reference to the class.
152+
* Relaxed `ProtocolType` requirement on `ProtocolObject`.
152153

153154
### Deprecated
154155
* Soft deprecated using `msg_send!` without a comma between arguments (i.e.

crates/objc2/src/macros/extern_protocol.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ macro_rules! __inner_extern_protocol {
184184
$(#[$impl_m])*
185185
unsafe impl<T> $name for $crate::runtime::ProtocolObject<T>
186186
where
187-
T: ?$crate::__macro_helpers::Sized + $crate::ProtocolType + $name
187+
T: ?$crate::__macro_helpers::Sized + $name
188188
{}
189189

190190
// SAFETY: The specified name is ensured by caller to be a protocol,

crates/objc2/src/mutability.rs

+10-13
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
use core::marker::PhantomData;
3434

3535
use crate::runtime::{AnyObject, ProtocolObject};
36-
use crate::{ClassType, Message, ProtocolType};
36+
use crate::{ClassType, Message};
3737

3838
mod private_mutability {
3939
pub trait Sealed {}
@@ -269,7 +269,7 @@ mod private_traits {
269269
}
270270

271271
impl<T: ?Sized + ClassType> private_traits::Sealed for T {}
272-
impl<P: ?Sized + ProtocolType> private_traits::Sealed for ProtocolObject<P> {}
272+
impl<P: ?Sized> private_traits::Sealed for ProtocolObject<P> {}
273273
impl private_traits::Sealed for AnyObject {}
274274

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

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

@@ -336,7 +336,7 @@ impl MutabilityIsRetainable for InteriorMutable {}
336336
impl MutabilityIsRetainable for MainThreadOnly {}
337337

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

341341
/// Marker trait for classes that can be allocated from any thread.
342342
///
@@ -367,10 +367,7 @@ unsafe impl<T: ?Sized + ClassType> IsAllocableAnyThread for T where
367367
T::Mutability: MutabilityIsAllocableAnyThread
368368
{
369369
}
370-
unsafe impl<P: ?Sized + ProtocolType + IsAllocableAnyThread> IsAllocableAnyThread
371-
for ProtocolObject<P>
372-
{
373-
}
370+
unsafe impl<P: ?Sized + IsAllocableAnyThread> IsAllocableAnyThread for ProtocolObject<P> {}
374371

375372
/// Marker trait for classes that may feasibly be used behind a mutable
376373
/// reference.
@@ -401,7 +398,7 @@ unsafe impl<T: ?Sized + ClassType> IsAllowedMutable for T where
401398
T::Mutability: MutabilityIsAllowedMutable
402399
{
403400
}
404-
unsafe impl<P: ?Sized + ProtocolType + IsAllowedMutable> IsAllowedMutable for ProtocolObject<P> {}
401+
unsafe impl<P: ?Sized + IsAllowedMutable> IsAllowedMutable for ProtocolObject<P> {}
405402
// SAFETY: Same as for root classes.
406403
unsafe impl IsAllowedMutable for AnyObject {}
407404

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

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

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

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

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

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

592-
unsafe impl<P: ?Sized + ProtocolType> CounterpartOrSelf for ProtocolObject<P> {
589+
unsafe impl<P: ?Sized> CounterpartOrSelf for ProtocolObject<P> {
593590
// SAFETY: The only place where this would differ from `Self` is for
594591
// classes with `MutableWithImmutableSuperclass<IS>`.
595592
//

crates/objc2/src/runtime/protocol_object.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::encode::{Encoding, RefEncode};
77
use crate::rc::{autoreleasepool_leaking, Id};
88
use crate::runtime::__nsstring::nsstring_to_str;
99
use crate::runtime::{AnyObject, NSObjectProtocol};
10-
use crate::{Message, ProtocolType};
10+
use crate::Message;
1111

1212
/// An internal helper trait for [`ProtocolObject`].
1313
///
@@ -57,25 +57,25 @@ pub unsafe trait ImplementedBy<T: ?Sized + Message> {
5757
/// ```
5858
#[doc(alias = "id")]
5959
#[repr(C)]
60-
pub struct ProtocolObject<P: ?Sized + ProtocolType> {
60+
pub struct ProtocolObject<P: ?Sized> {
6161
inner: AnyObject,
6262
p: PhantomData<P>,
6363
}
6464

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

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

74-
impl<P: ?Sized + ProtocolType> ProtocolObject<P> {
74+
impl<P: ?Sized> ProtocolObject<P> {
7575
/// Get an immutable type-erased reference from a type implementing a
7676
/// protocol.
7777
#[inline]
78-
pub fn from_ref<T: Message>(obj: &T) -> &Self
78+
pub fn from_ref<T: ?Sized + Message>(obj: &T) -> &Self
7979
where
8080
P: ImplementedBy<T>,
8181
{
@@ -89,7 +89,7 @@ impl<P: ?Sized + ProtocolType> ProtocolObject<P> {
8989
/// Get a mutable type-erased reference from a type implementing a
9090
/// protocol.
9191
#[inline]
92-
pub fn from_mut<T: Message>(obj: &mut T) -> &mut Self
92+
pub fn from_mut<T: ?Sized + Message>(obj: &mut T) -> &mut Self
9393
where
9494
P: ImplementedBy<T>,
9595
{
@@ -118,24 +118,24 @@ impl<P: ?Sized + ProtocolType> ProtocolObject<P> {
118118
}
119119
}
120120

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

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

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

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

162-
impl<P, T> AsRef<ProtocolObject<T>> for ProtocolObject<P>
162+
impl<P: ?Sized, T> AsRef<ProtocolObject<T>> for ProtocolObject<P>
163163
where
164-
P: ?Sized + ProtocolType,
165-
T: ?Sized + ProtocolType + ImplementedBy<ProtocolObject<P>>,
164+
T: ?Sized + ImplementedBy<ProtocolObject<P>>,
166165
{
167166
#[inline]
168167
fn as_ref(&self) -> &ProtocolObject<T> {
169168
ProtocolObject::from_ref(self)
170169
}
171170
}
172171

173-
impl<P, T> AsMut<ProtocolObject<T>> for ProtocolObject<P>
172+
impl<P: ?Sized, T> AsMut<ProtocolObject<T>> for ProtocolObject<P>
174173
where
175-
P: ?Sized + ProtocolType,
176-
T: ?Sized + ProtocolType + ImplementedBy<ProtocolObject<P>>,
174+
T: ?Sized + ImplementedBy<ProtocolObject<P>>,
177175
{
178176
#[inline]
179177
fn as_mut(&mut self) -> &mut ProtocolObject<T> {
180178
ProtocolObject::from_mut(self)
181179
}
182180
}
183181

184-
// TODO: Maybe iplement Borrow + BorrowMut?
182+
// TODO: Maybe implement Borrow + BorrowMut?
185183

186184
#[cfg(test)]
187185
#[allow(clippy::missing_safety_doc)]
@@ -194,7 +192,9 @@ mod tests {
194192
use super::*;
195193
use crate::mutability::Mutable;
196194
use crate::runtime::{NSObject, NSObjectProtocol};
197-
use crate::{declare_class, extern_methods, extern_protocol, ClassType, DeclaredClass};
195+
use crate::{
196+
declare_class, extern_methods, extern_protocol, ClassType, DeclaredClass, ProtocolType,
197+
};
198198

199199
extern_protocol!(
200200
unsafe trait Foo {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//! Ensure that `ProtocolObject` cannot be incorrectly constructed.
2+
use icrate::Foundation::NSCopying;
3+
use objc2::runtime::{NSObject, NSObjectProtocol, ProtocolObject};
4+
5+
trait Foo {
6+
fn foo(&self) {}
7+
}
8+
9+
impl<T: ?Sized> Foo for T {}
10+
11+
fn main() {
12+
let obj = NSObject::new();
13+
let _: &ProtocolObject<NSObject> = ProtocolObject::from_ref(&*obj);
14+
let _: &ProtocolObject<dyn Send> = ProtocolObject::from_ref(&*obj);
15+
let _: &ProtocolObject<dyn Foo> = ProtocolObject::from_ref(&*obj);
16+
17+
// `NSObject` is neither `Send` nor `Sync`.
18+
let _: &ProtocolObject<dyn NSObjectProtocol + Send> = ProtocolObject::from_ref(&*obj);
19+
let _: &ProtocolObject<dyn NSObjectProtocol + Sync> = ProtocolObject::from_ref(&*obj);
20+
let _: &ProtocolObject<dyn NSObjectProtocol + Send + Sync> = ProtocolObject::from_ref(&*obj);
21+
22+
// `NSObject` is not `NSCopying`.
23+
let _: &ProtocolObject<dyn NSCopying> = ProtocolObject::from_ref(&*obj);
24+
25+
// `dyn NSCopying + Send` does not implement `ImplementedBy` (yet).
26+
let _: &ProtocolObject<dyn NSCopying + Send> = ProtocolObject::from_ref(&*obj);
27+
}

0 commit comments

Comments
 (0)