Skip to content

Commit 87bb19f

Browse files
committed
Make Class no longer implement Message directly
This is done so that: - `Id<T, O>` is correct for all `T: Message` (currently `Id<Class, _>` is possible). - `ClassBuilder::add_method` doesn't accept functions that take `&Class` as the receiver.
1 parent 802f8c2 commit 87bb19f

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

objc2/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5858

5959
If you previously used `*mut Object` or `&Object` as the receiver, message
6060
sending should work exactly as before.
61+
* **BREAKING**: `Class` no longer implements `Message` (but it can still be
62+
used as the receiver in `msg_send!`, so this is unlikely to break anything
63+
in practice).
6164

6265
### Fixed
6366
* Properly sealed the `MessageArguments` trait (it already had a hidden

objc2/src/declare.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use crate::{ffi, Encode, EncodeArguments, Encoding, Message};
4848
/// Types that can be used as the implementation of an Objective-C method.
4949
pub trait MethodImplementation {
5050
/// The callee type of the method.
51-
type Callee: Message + ?Sized;
51+
type Callee: ?Sized;
5252
/// The return type of the method.
5353
type Ret: Encode;
5454
/// The argument types of the method.
@@ -75,13 +75,32 @@ macro_rules! method_decl_impl {
7575
}
7676
}
7777
);
78+
(@$s:ident, $r:ident, $f:ty, $($t:ident),*) => (
79+
impl<$r, $($t),*> MethodImplementation for $f
80+
where
81+
$r: Encode,
82+
$($t: Encode,)*
83+
{
84+
type Callee = $s;
85+
type Ret = $r;
86+
type Args = ($($t,)*);
87+
88+
fn imp(self) -> Imp {
89+
unsafe { mem::transmute(self) }
90+
}
91+
}
92+
);
7893
($($t:ident),*) => (
7994
method_decl_impl!(-T, R, extern "C" fn(&T, Sel $(, $t)*) -> R, $($t),*);
8095
method_decl_impl!(-T, R, extern "C" fn(&mut T, Sel $(, $t)*) -> R, $($t),*);
8196
method_decl_impl!(-T, R, unsafe extern "C" fn(*const T, Sel $(, $t)*) -> R, $($t),*);
8297
method_decl_impl!(-T, R, unsafe extern "C" fn(*mut T, Sel $(, $t)*) -> R, $($t),*);
8398
method_decl_impl!(-T, R, unsafe extern "C" fn(&T, Sel $(, $t)*) -> R, $($t),*);
8499
method_decl_impl!(-T, R, unsafe extern "C" fn(&mut T, Sel $(, $t)*) -> R, $($t),*);
100+
101+
method_decl_impl!(@Class, R, extern "C" fn(&Class, Sel $(, $t)*) -> R, $($t),*);
102+
method_decl_impl!(@Class, R, unsafe extern "C" fn(*const Class, Sel $(, $t)*) -> R, $($t),*);
103+
method_decl_impl!(@Class, R, unsafe extern "C" fn(&Class, Sel $(, $t)*) -> R, $($t),*);
85104
);
86105
}
87106

@@ -200,7 +219,7 @@ impl ClassBuilder {
200219
/// when the method is invoked from Objective-C.
201220
pub unsafe fn add_method<T, F>(&mut self, sel: Sel, func: F)
202221
where
203-
T: Message + ?Sized, // TODO: Disallow `Class`
222+
T: Message + ?Sized,
204223
F: MethodImplementation<Callee = T>,
205224
{
206225
let encs = F::Args::ENCODINGS;

objc2/src/message/mod.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ use self::verify::{verify_message_signature, VerificationError};
4343

4444
/// Types that can be sent Objective-C messages.
4545
///
46-
/// Examples include objects, classes, and blocks.
47-
///
4846
/// Implementing this provides [`MessageReceiver`] implementations for common
4947
/// pointer types and references to the type, which allows using them as the
5048
/// receiver (first argument) in the [`msg_send!`][`crate::msg_send`] macro.
@@ -54,6 +52,9 @@ use self::verify::{verify_message_signature, VerificationError};
5452
/// A pointer to the type must be able to be the receiver of an Objective-C
5553
/// message sent with [`objc_msgSend`] or similar.
5654
///
55+
/// The object must also respond to the `retain`, `release` and `autorelease`
56+
/// messages, as that allows it to be used with [`rc::Id`][`Id`].
57+
///
5758
/// Additionally, the type must implement [`RefEncode`] and adhere to the
5859
/// safety requirements therein.
5960
///
@@ -65,8 +66,6 @@ unsafe impl<T: Message + ?Sized> Message for ManuallyDrop<T> {}
6566

6667
unsafe impl Message for Object {}
6768

68-
unsafe impl Message for Class {}
69-
7069
// TODO: Make this fully private
7170
pub(crate) mod private {
7271
use super::*;
@@ -85,10 +84,15 @@ pub(crate) mod private {
8584

8685
impl<'a, T: Message + ?Sized, O: Ownership> Sealed for &'a ManuallyDrop<Id<T, O>> {}
8786
impl<'a, T: Message + ?Sized> Sealed for &'a mut ManuallyDrop<Id<T, Owned>> {}
87+
88+
impl Sealed for *const Class {}
89+
impl<'a> Sealed for &'a Class {}
8890
}
8991

9092
/// Types that can directly be used as the receiver of Objective-C messages.
9193
///
94+
/// Examples include objects, classes, and blocks.
95+
///
9296
/// This is a sealed trait (for now) that is automatically implemented for
9397
/// pointers to types implementing [`Message`], so that code can be generic
9498
/// over the message receiver.
@@ -281,6 +285,20 @@ unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut ManuallyDrop<Id
281285
}
282286
}
283287

288+
unsafe impl MessageReceiver for *const Class {
289+
#[inline]
290+
fn as_raw_receiver(self) -> *mut Object {
291+
self as *mut Class as *mut Object
292+
}
293+
}
294+
295+
unsafe impl<'a> MessageReceiver for &'a Class {
296+
#[inline]
297+
fn as_raw_receiver(self) -> *mut Object {
298+
self as *const Class as *mut Class as *mut Object
299+
}
300+
}
301+
284302
/// Types that may be used as the arguments of an Objective-C message.
285303
///
286304
/// This is implemented for tuples of up to 12 arguments, where each argument

0 commit comments

Comments
 (0)