Skip to content

Commit ff33337

Browse files
committed
Relax requirements for receivers in MethodImplementation
1 parent 284f988 commit ff33337

11 files changed

+160
-215
lines changed

crates/objc2/CHANGELOG.md

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

4343
In particular automatic conversion of `bool` is not supported in
4444
`MessageReceiver`.
45+
* Relaxed the requirements for receivers in `MethodImplementation`; now,
46+
anything that implements `MessageReceiver` can be used as the receiver of
47+
a method.
4548

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

crates/objc2/src/macros/declare_class.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,9 @@
8282
///
8383
/// On instance methods, you can freely choose between different types of
8484
/// receivers, e.g. `&self`, `this: *const Self`, `&mut self`, and so on. Note
85-
/// though that using raw pointers requires the function to be `unsafe`, and
86-
/// using `&mut self` requires the class' mutability to be
85+
/// though that using `&mut self` requires the class' mutability to be
8786
/// [`IsAllowedMutable`].
88-
/// If you require mutation of your class' instance variables, consider using
87+
/// If you need mutation of your class' instance variables, consider using
8988
/// [`Cell`] or similar instead.
9089
///
9190
/// The desired selector can be specified using the `#[method(my:selector:)]`

crates/objc2/src/runtime/method_implementation.rs

Lines changed: 20 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ use core::mem;
22

33
use crate::__macro_helpers::IdReturnValue;
44
use crate::encode::{EncodeArgument, EncodeArguments, EncodeReturn, RefEncode};
5-
use crate::mutability::IsAllowedMutable;
65
use crate::rc::Allocated;
7-
use crate::runtime::{AnyClass, Imp, Sel};
6+
use crate::runtime::{Imp, MessageReceiver, Sel};
87
use crate::Message;
98

109
mod private {
@@ -19,7 +18,7 @@ mod private {
1918
// Note: `Sized` is intentionally added to make the trait not object safe.
2019
pub trait MethodImplementation: private::Sealed + Sized {
2120
/// The callee type of the method.
22-
type Callee: RefEncode + ?Sized;
21+
type Callee: ?Sized + RefEncode;
2322
/// The return type of the method.
2423
type Ret: EncodeReturn;
2524
/// The argument types of the method.
@@ -29,67 +28,39 @@ pub trait MethodImplementation: private::Sealed + Sized {
2928
fn __imp(self) -> Imp;
3029
}
3130

32-
macro_rules! method_impl_generic {
33-
(<$($l:lifetime),*> T: $t_bound:ident $(+ $t_bound2:ident)?, $r:ident, $f:ty, $($t:ident),*) => {
34-
impl<$($l,)* T, $r, $($t),*> private::Sealed for $f
31+
macro_rules! method_impl_inner {
32+
($(($unsafe:ident))? $abi:literal; $($t:ident),*) => {
33+
impl<T, R, $($t),*> private::Sealed for $($unsafe)? extern $abi fn(T, Sel $(, $t)*) -> R
3534
where
36-
T: ?Sized + $t_bound $(+ $t_bound2)?,
37-
$r: EncodeReturn,
35+
T: ?Sized + MessageReceiver,
36+
R: EncodeReturn,
3837
$($t: EncodeArgument,)*
3938
{}
4039

41-
impl<$($l,)* T, $r, $($t),*> MethodImplementation for $f
40+
impl<T, R, $($t),*> MethodImplementation for $($unsafe)? extern $abi fn(T, Sel $(, $t)*) -> R
4241
where
43-
T: ?Sized + $t_bound $(+ $t_bound2)?,
44-
$r: EncodeReturn,
42+
T: ?Sized + MessageReceiver,
43+
R: EncodeReturn,
4544
$($t: EncodeArgument,)*
4645
{
47-
type Callee = T;
48-
type Ret = $r;
49-
type Args = ($($t,)*);
50-
51-
fn __imp(self) -> Imp {
52-
unsafe { mem::transmute(self) }
53-
}
54-
}
55-
};
56-
}
57-
58-
macro_rules! method_impl_concrete {
59-
(<$($l:lifetime),*> $callee:ident, $r:ident, $f:ty, $($t:ident),*) => {
60-
impl<$($l,)* $r, $($t),*> private::Sealed for $f
61-
where
62-
$r: EncodeReturn,
63-
$($t: EncodeArgument,)*
64-
{}
65-
66-
impl<$($l,)* $r, $($t),*> MethodImplementation for $f
67-
where
68-
$r: EncodeReturn,
69-
$($t: EncodeArgument,)*
70-
{
71-
type Callee = $callee;
72-
type Ret = $r;
46+
type Callee = T::__Inner;
47+
type Ret = R;
7348
type Args = ($($t,)*);
7449

7550
fn __imp(self) -> Imp {
51+
// SAFETY: Transmuting to an `unsafe` function pointer
7652
unsafe { mem::transmute(self) }
7753
}
7854
}
79-
};
80-
}
8155

82-
macro_rules! method_impl_allocated {
83-
(<> Allocated<T>, $f:ty, $($t:ident),*) => {
84-
#[doc(hidden)]
85-
impl<T, $($t),*> private::Sealed for $f
56+
impl<T, $($t),*> private::Sealed for $($unsafe)? extern $abi fn(Allocated<T>, Sel $(, $t)*) -> IdReturnValue
8657
where
8758
T: ?Sized + Message,
8859
$($t: EncodeArgument,)*
8960
{}
9061

9162
#[doc(hidden)]
92-
impl<T, $($t),*> MethodImplementation for $f
63+
impl<T, $($t),*> MethodImplementation for $($unsafe)? extern $abi fn(Allocated<T>, Sel $(, $t)*) -> IdReturnValue
9364
where
9465
T: ?Sized + Message,
9566
$($t: EncodeArgument,)*
@@ -113,29 +84,14 @@ macro_rules! method_impl_allocated {
11384
};
11485
}
11586

116-
macro_rules! method_impl_abi {
117-
($abi:literal; $($t:ident),*) => {
118-
method_impl_generic!(<'a> T: Message, R, extern $abi fn(&'a T, Sel $(, $t)*) -> R, $($t),*);
119-
method_impl_generic!(<'a> T: Message + IsAllowedMutable, R, extern $abi fn(&'a mut T, Sel $(, $t)*) -> R, $($t),*);
120-
method_impl_generic!(<> T: Message, R, unsafe extern $abi fn(*const T, Sel $(, $t)*) -> R, $($t),*);
121-
method_impl_generic!(<> T: Message, R, unsafe extern $abi fn(*mut T, Sel $(, $t)*) -> R, $($t),*);
122-
method_impl_generic!(<'a> T: Message, R, unsafe extern $abi fn(&'a T, Sel $(, $t)*) -> R, $($t),*);
123-
method_impl_generic!(<'a> T: Message + IsAllowedMutable, R, unsafe extern $abi fn(&'a mut T, Sel $(, $t)*) -> R, $($t),*);
124-
125-
method_impl_concrete!(<'a> AnyClass, R, extern $abi fn(&'a AnyClass, Sel $(, $t)*) -> R, $($t),*);
126-
method_impl_concrete!(<> AnyClass, R, unsafe extern $abi fn(*const AnyClass, Sel $(, $t)*) -> R, $($t),*);
127-
method_impl_concrete!(<'a> AnyClass, R, unsafe extern $abi fn(&'a AnyClass, Sel $(, $t)*) -> R, $($t),*);
128-
129-
method_impl_allocated!(<> Allocated<T>, extern $abi fn(Allocated<T>, Sel $(, $t)*) -> IdReturnValue, $($t),*);
130-
method_impl_allocated!(<> Allocated<T>, unsafe extern $abi fn(Allocated<T>, Sel $(, $t)*) -> IdReturnValue, $($t),*);
131-
};
132-
}
133-
13487
macro_rules! method_impl {
13588
($($t:ident),*) => {
136-
method_impl_abi!("C"; $($t),*);
89+
method_impl_inner!((unsafe) "C"; $($t),*);
90+
method_impl_inner!("C"; $($t),*);
91+
#[cfg(feature = "unstable-c-unwind")]
92+
method_impl_inner!((unsafe) "C-unwind"; $($t),*);
13793
#[cfg(feature = "unstable-c-unwind")]
138-
method_impl_abi!("C-unwind"; $($t),*);
94+
method_impl_inner!("C-unwind"; $($t),*);
13995
};
14096
}
14197

crates/objc2/tests/declare_class.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![deny(deprecated, unreachable_code)]
2-
use core::ptr;
2+
use core::ptr::{self, NonNull};
33

44
use objc2::declare::IvarEncode;
55
use objc2::mutability::{Immutable, Mutable};
@@ -538,3 +538,30 @@ fn out_param3() {
538538
fn out_param4() {
539539
OutParam::unsupported4(None);
540540
}
541+
542+
#[test]
543+
fn test_pointer_receiver_allowed() {
544+
declare_class!(
545+
#[derive(Debug)]
546+
struct PointerReceiver;
547+
548+
unsafe impl ClassType for PointerReceiver {
549+
type Super = NSObject;
550+
type Mutability = Immutable;
551+
const NAME: &'static str = "PointerReceiver";
552+
}
553+
554+
unsafe impl PointerReceiver {
555+
#[method(constPtr)]
556+
fn const_ptr(_this: *const Self) {}
557+
558+
#[method(mutPtr)]
559+
fn mut_ptr(_this: *mut Self) {}
560+
561+
#[method(nonnullPtr)]
562+
fn nonnull_ptr(_this: NonNull<Self>) {}
563+
}
564+
);
565+
566+
let _ = PointerReceiver::class();
567+
}

0 commit comments

Comments
 (0)