Skip to content

Commit 9bd6cc4

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 dbddcb8 commit 9bd6cc4

File tree

5 files changed

+51
-10
lines changed

5 files changed

+51
-10
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::*;
@@ -84,10 +83,15 @@ pub(crate) mod private {
8483
impl<'a, T: Message + ?Sized> Sealed for &'a mut Id<T, Owned> {}
8584

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

8991
/// Types that can directly be used as the receiver of Objective-C messages.
9092
///
93+
/// Examples include objects, classes, and blocks.
94+
///
9195
/// This is a sealed trait (for now) that is automatically implemented for
9296
/// pointers to types implementing [`Message`], so that code can be generic
9397
/// over the message receiver.
@@ -273,6 +277,20 @@ unsafe impl<T: Message + ?Sized, O: Ownership> MessageReceiver for ManuallyDrop<
273277
}
274278
}
275279

280+
unsafe impl MessageReceiver for *const Class {
281+
#[inline]
282+
fn as_raw_receiver(self) -> *mut Object {
283+
self as *mut Class as *mut Object
284+
}
285+
}
286+
287+
unsafe impl<'a> MessageReceiver for &'a Class {
288+
#[inline]
289+
fn as_raw_receiver(self) -> *mut Object {
290+
self as *const Class as *mut Class as *mut Object
291+
}
292+
}
293+
276294
/// Types that may be used as the arguments of an Objective-C message.
277295
///
278296
/// This is implemented for tuples of up to 12 arguments, where each argument

tests/ui/fn_ptr_reference_method.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `extern "C" fn(_, _, _): MethodImplementation` is
1515
for<'r> extern "C" fn(&'r T, objc2::runtime::Sel, A, B, C, D, E) -> R
1616
for<'r> extern "C" fn(&'r T, objc2::runtime::Sel, A, B, C, D, E, F) -> R
1717
for<'r> extern "C" fn(&'r T, objc2::runtime::Sel, A, B, C, D, E, F, G) -> R
18-
and 70 others
18+
and 109 others
1919
note: required by a bound in `ClassBuilder::add_method`
2020
--> $WORKSPACE/objc2/src/declare.rs
2121
|
@@ -39,7 +39,7 @@ error[E0277]: the trait bound `for<'r> extern "C" fn(_, _, &'r objc2::runtime::O
3939
for<'r> extern "C" fn(&'r T, objc2::runtime::Sel, A, B, C, D, E) -> R
4040
for<'r> extern "C" fn(&'r T, objc2::runtime::Sel, A, B, C, D, E, F) -> R
4141
for<'r> extern "C" fn(&'r T, objc2::runtime::Sel, A, B, C, D, E, F, G) -> R
42-
and 70 others
42+
and 109 others
4343
note: required by a bound in `ClassBuilder::add_method`
4444
--> $WORKSPACE/objc2/src/declare.rs
4545
|

tests/ui/msg_send_only_message.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ error[E0277]: the trait bound `{integer}: MessageReceiver` is not satisfied
99
&'a T
1010
&'a mut Id<T, objc2::rc::Owned>
1111
&'a mut T
12+
&'a objc2::runtime::Class
1213
*const T
14+
*const objc2::runtime::Class
1315
*mut T
14-
ManuallyDrop<Id<T, O>>
15-
NonNull<T>
16+
and 2 others
1617
= note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)

0 commit comments

Comments
 (0)