Skip to content

Commit 65b1285

Browse files
committed
Move MethodImplementation trait to runtime module
1 parent 7dc1b17 commit 65b1285

File tree

11 files changed

+309
-294
lines changed

11 files changed

+309
-294
lines changed

crates/objc2/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2525
This effectively means you can now `copy` a `ProtocolObject<dyn NSCopying>`.
2626
* **BREAKING**: Allow implementing `DefaultId` for any type, not just those
2727
who are `IsAllocableAnyThread`.
28+
* **BREAKING**: Moved the `MethodImplementation` trait from the `declare`
29+
module to the `runtime` module.
2830

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

crates/objc2/src/__macro_helpers/declare_class.rs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,27 @@
1-
use crate::declare::__IdReturnValue;
1+
use objc2_encode::Encoding;
2+
3+
use crate::encode::Encode;
24
use crate::rc::{Allocated, Id};
5+
use crate::runtime::AnyObject;
36
use crate::{ClassType, Message, MessageReceiver};
47

58
use super::{CopyOrMutCopy, Init, MaybeUnwrap, New, Other};
69
use crate::mutability;
710

11+
/// Helper type for implementing `MethodImplementation` with a receiver of
12+
/// `Allocated<T>`, without exposing that implementation to users.
13+
//
14+
// Must be private, soundness of MethodImplementation relies on this.
15+
#[doc(hidden)]
16+
#[repr(transparent)]
17+
#[derive(Debug)]
18+
pub struct IdReturnValue(pub(crate) *mut AnyObject);
19+
20+
// SAFETY: `IdReturnValue` is `#[repr(transparent)]`
21+
unsafe impl Encode for IdReturnValue {
22+
const ENCODING: Encoding = <*mut AnyObject>::ENCODING;
23+
}
24+
825
// One could imagine a different design where we had a method like
926
// `fn convert_receiver()`, but that won't work in `declare_class!` since we
1027
// can't actually modify the `self` argument (e.g. `let self = foo(self)` is
@@ -13,7 +30,7 @@ use crate::mutability;
1330
// See `MsgSendId` and `RetainSemantics` for details on the retain semantics
1431
// we're following here.
1532
pub trait MessageRecieveId<Receiver, Ret> {
16-
fn into_return(obj: Ret) -> __IdReturnValue;
33+
fn into_return(obj: Ret) -> IdReturnValue;
1734
}
1835

1936
// Receiver and return type have no correlation
@@ -23,7 +40,7 @@ where
2340
Ret: MaybeOptionId,
2441
{
2542
#[inline]
26-
fn into_return(obj: Ret) -> __IdReturnValue {
43+
fn into_return(obj: Ret) -> IdReturnValue {
2744
obj.consumed_return()
2845
}
2946
}
@@ -42,7 +59,7 @@ where
4259
Ret: MaybeOptionId<Input = Id<T>>,
4360
{
4461
#[inline]
45-
fn into_return(obj: Ret) -> __IdReturnValue {
62+
fn into_return(obj: Ret) -> IdReturnValue {
4663
obj.consumed_return()
4764
}
4865
}
@@ -54,7 +71,7 @@ where
5471
Ret: MaybeOptionId,
5572
{
5673
#[inline]
57-
fn into_return(obj: Ret) -> __IdReturnValue {
74+
fn into_return(obj: Ret) -> IdReturnValue {
5875
obj.consumed_return()
5976
}
6077
}
@@ -66,7 +83,7 @@ where
6683
Ret: MaybeOptionId,
6784
{
6885
#[inline]
69-
fn into_return(obj: Ret) -> __IdReturnValue {
86+
fn into_return(obj: Ret) -> IdReturnValue {
7087
obj.autorelease_return()
7188
}
7289
}
@@ -75,35 +92,35 @@ where
7592
///
7693
/// (Both of those are valid return types from declare_class! `#[method_id]`).
7794
pub trait MaybeOptionId: MaybeUnwrap {
78-
fn consumed_return(self) -> __IdReturnValue;
79-
fn autorelease_return(self) -> __IdReturnValue;
95+
fn consumed_return(self) -> IdReturnValue;
96+
fn autorelease_return(self) -> IdReturnValue;
8097
}
8198

8299
impl<T: Message> MaybeOptionId for Id<T> {
83100
#[inline]
84-
fn consumed_return(self) -> __IdReturnValue {
101+
fn consumed_return(self) -> IdReturnValue {
85102
let ptr: *mut T = Id::consume_as_ptr(self);
86-
__IdReturnValue(ptr.cast())
103+
IdReturnValue(ptr.cast())
87104
}
88105

89106
#[inline]
90-
fn autorelease_return(self) -> __IdReturnValue {
107+
fn autorelease_return(self) -> IdReturnValue {
91108
let ptr: *mut T = Id::autorelease_return(self);
92-
__IdReturnValue(ptr.cast())
109+
IdReturnValue(ptr.cast())
93110
}
94111
}
95112

96113
impl<T: Message> MaybeOptionId for Option<Id<T>> {
97114
#[inline]
98-
fn consumed_return(self) -> __IdReturnValue {
115+
fn consumed_return(self) -> IdReturnValue {
99116
let ptr: *mut T = Id::consume_as_ptr_option(self);
100-
__IdReturnValue(ptr.cast())
117+
IdReturnValue(ptr.cast())
101118
}
102119

103120
#[inline]
104-
fn autorelease_return(self) -> __IdReturnValue {
121+
fn autorelease_return(self) -> IdReturnValue {
105122
let ptr: *mut T = Id::autorelease_return_option(self);
106-
__IdReturnValue(ptr.cast())
123+
IdReturnValue(ptr.cast())
107124
}
108125
}
109126

crates/objc2/src/__macro_helpers/mod.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ use core::ptr;
55
use std::collections::HashSet;
66

77
use crate::declare::ClassBuilder;
8-
use crate::declare::MethodImplementation;
98
use crate::encode::Encode;
109
use crate::message::__TupleExtender;
1110
use crate::rc::{Allocated, Id};
1211
#[cfg(all(debug_assertions, feature = "verify"))]
1312
use crate::runtime::MethodDescription;
14-
use crate::runtime::{AnyClass, AnyObject, AnyProtocol, Sel};
13+
use crate::runtime::{AnyClass, AnyObject, AnyProtocol, MethodImplementation, Sel};
1514
use crate::{Message, MessageArguments, MessageReceiver};
1615

1716
pub use core::borrow::{Borrow, BorrowMut};
@@ -35,11 +34,11 @@ mod writeback;
3534

3635
pub use self::cache::{CachedClass, CachedSel};
3736
pub use self::common_selectors::{alloc_sel, dealloc_sel, init_sel, new_sel};
37+
pub use self::convert::{ConvertArgument, ConvertReturn};
3838
pub use self::declare_class::{
39-
assert_mutability_matches_superclass_mutability, MaybeOptionId, MessageRecieveId,
40-
ValidSubclassMutability,
39+
assert_mutability_matches_superclass_mutability, IdReturnValue, MaybeOptionId,
40+
MessageRecieveId, ValidSubclassMutability,
4141
};
42-
pub use convert::{ConvertArgument, ConvertReturn};
4342

4443
/// Helper for specifying the retain semantics for a given selector family.
4544
///

crates/objc2/src/declare/mod.rs

Lines changed: 3 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ use core::ptr;
1818
use core::ptr::NonNull;
1919
use std::ffi::CString;
2020

21-
use crate::encode::{Encode, EncodeArgument, EncodeArguments, EncodeReturn, Encoding, RefEncode};
21+
use crate::encode::{Encode, EncodeArguments, EncodeReturn, Encoding};
2222
use crate::ffi;
23-
use crate::mutability::IsMutable;
24-
use crate::rc::Allocated;
25-
use crate::runtime::{AnyClass, AnyObject, AnyProtocol, Bool, Imp, Sel};
23+
use crate::runtime::{AnyClass, AnyObject, AnyProtocol, Bool, Imp, MethodImplementation, Sel};
2624
use crate::sel;
2725
use crate::Message;
2826

@@ -31,171 +29,6 @@ pub use ivar_bool::IvarBool;
3129
pub use ivar_drop::IvarDrop;
3230
pub use ivar_encode::IvarEncode;
3331

34-
pub(crate) mod private {
35-
pub trait Sealed {}
36-
}
37-
38-
/// Types that can be used as the implementation of an Objective-C method.
39-
///
40-
/// This is a sealed trait that is implemented for a lot of `extern "C"`
41-
/// function pointer types.
42-
//
43-
// Note: `Sized` is intentionally added to make the trait not object safe.
44-
pub trait MethodImplementation: private::Sealed + Sized {
45-
/// The callee type of the method.
46-
type Callee: RefEncode + ?Sized;
47-
/// The return type of the method.
48-
type Ret: EncodeReturn;
49-
/// The argument types of the method.
50-
type Args: EncodeArguments;
51-
52-
#[doc(hidden)]
53-
fn __imp(self) -> Imp;
54-
}
55-
56-
macro_rules! method_impl_generic {
57-
(<$($l:lifetime),*> T: $t_bound:ident $(+ $t_bound2:ident)?, $r:ident, $f:ty, $($t:ident),*) => {
58-
impl<$($l,)* T, $r, $($t),*> private::Sealed for $f
59-
where
60-
T: ?Sized + $t_bound $(+ $t_bound2)?,
61-
$r: EncodeReturn,
62-
$($t: EncodeArgument,)*
63-
{}
64-
65-
impl<$($l,)* T, $r, $($t),*> MethodImplementation for $f
66-
where
67-
T: ?Sized + $t_bound $(+ $t_bound2)?,
68-
$r: EncodeReturn,
69-
$($t: EncodeArgument,)*
70-
{
71-
type Callee = T;
72-
type Ret = $r;
73-
type Args = ($($t,)*);
74-
75-
fn __imp(self) -> Imp {
76-
unsafe { mem::transmute(self) }
77-
}
78-
}
79-
};
80-
}
81-
82-
macro_rules! method_impl_concrete {
83-
(<$($l:lifetime),*> $callee:ident, $r:ident, $f:ty, $($t:ident),*) => {
84-
impl<$($l,)* $r, $($t),*> private::Sealed for $f
85-
where
86-
$r: EncodeReturn,
87-
$($t: EncodeArgument,)*
88-
{}
89-
90-
impl<$($l,)* $r, $($t),*> MethodImplementation for $f
91-
where
92-
$r: EncodeReturn,
93-
$($t: EncodeArgument,)*
94-
{
95-
type Callee = $callee;
96-
type Ret = $r;
97-
type Args = ($($t,)*);
98-
99-
fn __imp(self) -> Imp {
100-
unsafe { mem::transmute(self) }
101-
}
102-
}
103-
};
104-
}
105-
106-
macro_rules! method_impl_allocated {
107-
(<> Allocated<T>, $f:ty, $($t:ident),*) => {
108-
#[doc(hidden)]
109-
impl<T, $($t),*> private::Sealed for $f
110-
where
111-
T: ?Sized + Message,
112-
$($t: EncodeArgument,)*
113-
{}
114-
115-
#[doc(hidden)]
116-
impl<T, $($t),*> MethodImplementation for $f
117-
where
118-
T: ?Sized + Message,
119-
$($t: EncodeArgument,)*
120-
{
121-
type Callee = T;
122-
type Ret = __IdReturnValue;
123-
type Args = ($($t,)*);
124-
125-
fn __imp(self) -> Imp {
126-
// SAFETY: `Allocated<T>` is the same as `NonNull<T>`, except
127-
// with the assumption of a +1 calling convention.
128-
//
129-
// The calling convention is ensured to be upheld by having
130-
// `__IdReturnValue` in the type, since that type is private
131-
// and hence only internal macros like `#[method_id]` will be
132-
// able to produce it (and that, in turn, only allows it if
133-
// the selector is `init` as checked by `MessageRecieveId`).
134-
unsafe { mem::transmute(self) }
135-
}
136-
}
137-
};
138-
}
139-
140-
macro_rules! method_impl_abi {
141-
($abi:literal; $($t:ident),*) => {
142-
method_impl_generic!(<'a> T: Message, R, extern $abi fn(&'a T, Sel $(, $t)*) -> R, $($t),*);
143-
method_impl_generic!(<'a> T: Message + IsMutable, R, extern $abi fn(&'a mut T, Sel $(, $t)*) -> R, $($t),*);
144-
method_impl_generic!(<> T: Message, R, unsafe extern $abi fn(*const T, Sel $(, $t)*) -> R, $($t),*);
145-
method_impl_generic!(<> T: Message, R, unsafe extern $abi fn(*mut T, Sel $(, $t)*) -> R, $($t),*);
146-
method_impl_generic!(<'a> T: Message, R, unsafe extern $abi fn(&'a T, Sel $(, $t)*) -> R, $($t),*);
147-
method_impl_generic!(<'a> T: Message + IsMutable, R, unsafe extern $abi fn(&'a mut T, Sel $(, $t)*) -> R, $($t),*);
148-
149-
method_impl_concrete!(<'a> AnyObject, R, extern $abi fn(&'a mut AnyObject, Sel $(, $t)*) -> R, $($t),*);
150-
method_impl_concrete!(<'a> AnyObject, R, unsafe extern $abi fn(&'a mut AnyObject, Sel $(, $t)*) -> R, $($t),*);
151-
152-
method_impl_concrete!(<'a> AnyClass, R, extern $abi fn(&'a AnyClass, Sel $(, $t)*) -> R, $($t),*);
153-
method_impl_concrete!(<> AnyClass, R, unsafe extern $abi fn(*const AnyClass, Sel $(, $t)*) -> R, $($t),*);
154-
method_impl_concrete!(<'a> AnyClass, R, unsafe extern $abi fn(&'a AnyClass, Sel $(, $t)*) -> R, $($t),*);
155-
156-
method_impl_allocated!(<> Allocated<T>, extern $abi fn(Allocated<T>, Sel $(, $t)*) -> __IdReturnValue, $($t),*);
157-
method_impl_allocated!(<> Allocated<T>, unsafe extern $abi fn(Allocated<T>, Sel $(, $t)*) -> __IdReturnValue, $($t),*);
158-
};
159-
}
160-
161-
macro_rules! method_impl {
162-
($($t:ident),*) => {
163-
method_impl_abi!("C"; $($t),*);
164-
#[cfg(feature = "unstable-c-unwind")]
165-
method_impl_abi!("C-unwind"; $($t),*);
166-
};
167-
}
168-
169-
method_impl!();
170-
method_impl!(A);
171-
method_impl!(A, B);
172-
method_impl!(A, B, C);
173-
method_impl!(A, B, C, D);
174-
method_impl!(A, B, C, D, E);
175-
method_impl!(A, B, C, D, E, F);
176-
method_impl!(A, B, C, D, E, F, G);
177-
method_impl!(A, B, C, D, E, F, G, H);
178-
method_impl!(A, B, C, D, E, F, G, H, I);
179-
method_impl!(A, B, C, D, E, F, G, H, I, J);
180-
method_impl!(A, B, C, D, E, F, G, H, I, J, K);
181-
method_impl!(A, B, C, D, E, F, G, H, I, J, K, L);
182-
method_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M);
183-
method_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
184-
method_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
185-
method_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
186-
187-
/// Helper type for implementing `MethodImplementation` with a receiver of
188-
/// `Allocated<T>`, without exposing that implementation to users.
189-
#[doc(hidden)]
190-
#[repr(transparent)]
191-
#[derive(Debug)]
192-
pub struct __IdReturnValue(pub(crate) *mut AnyObject);
193-
194-
// SAFETY: `__IdReturnValue` is `#[repr(transparent)]`
195-
unsafe impl Encode for __IdReturnValue {
196-
const ENCODING: Encoding = <*mut AnyObject>::ENCODING;
197-
}
198-
19932
fn method_type_encoding(ret: &Encoding, args: &[Encoding]) -> CString {
20033
// First two arguments are always self and the selector
20134
let mut types = format!("{ret}{}{}", <*mut AnyObject>::ENCODING, Sel::ENCODING);
@@ -778,6 +611,7 @@ mod tests {
778611
use std::hash::Hash;
779612

780613
use super::*;
614+
use crate::encode::RefEncode;
781615
use crate::mutability::Immutable;
782616
use crate::rc::Id;
783617
use crate::runtime::{NSObject, NSObjectProtocol};

crates/objc2/src/macros/declare_class.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1116,7 +1116,7 @@ macro_rules! __declare_class_method_out_inner {
11161116
$($qualifiers)* extern "C" fn $name(
11171117
$($params_prefix)*
11181118
$($params_converted)*
1119-
) -> $crate::declare::__IdReturnValue {
1119+
) -> $crate::__macro_helpers::IdReturnValue {
11201120
$($body_prefix)*
11211121

11221122
let __objc2_result = $body;

0 commit comments

Comments
 (0)