@@ -54,22 +54,32 @@ macro_rules! sel {
54
54
55
55
/// Sends a message to an object or class.
56
56
///
57
- /// The first argument can be any type that implements [`MessageReceiver`],
58
- /// like a reference, a pointer, or an [`rc::Id`] to an object (where the
59
- /// object implements [`Message`]).
60
- ///
61
- /// In general this is wildly `unsafe`, even more so than sending messages in
57
+ /// This is wildly `unsafe`, even more so than sending messages in
62
58
/// Objective-C, because this macro doesn't know the expected types and
63
59
/// because Rust has more safety invariants to uphold. Make sure to review the
64
- /// safety section below.
60
+ /// safety section below!
61
+ ///
62
+ /// # General information
63
+ ///
64
+ /// The syntax is similar to the message syntax in Objective-C, except we
65
+ /// allow an optional comma between arguments (works better with rustfmt).
66
+ ///
67
+ /// The first argument (know as the "receiver") can be any type that
68
+ /// implements [`MessageReceiver`], like a reference or a pointer to an
69
+ /// object, or even a reference to an [`rc::Id`] containing an object.
70
+ ///
71
+ /// Each subsequent argument must implement [`Encode`].
65
72
///
66
- /// The syntax is similar to the message syntax in Objective-C.
73
+ /// Behind the scenes this translates into a call to [`sel!`], and afterwards
74
+ /// a fully qualified call to [`MessageReceiver::send_message`] (note that
75
+ /// this means that auto-dereferencing of the receiver is not supported,
76
+ /// making the ergonomics when using this slightly worse).
67
77
///
68
78
/// Variadic arguments are not currently supported.
69
79
///
70
80
/// [`MessageReceiver`]: crate::MessageReceiver
71
- /// [`Message`]: crate::Message
72
81
/// [`rc::Id`]: crate::rc::Id
82
+ /// [`Encode`]: crate::Encode
73
83
///
74
84
/// # Panics
75
85
///
@@ -83,13 +93,12 @@ macro_rules! sel {
83
93
///
84
94
/// # Safety
85
95
///
86
- /// The user must ensure that the selector is a valid method and is available
87
- /// on the given receiver.
96
+ /// This macro can't inspect header files to see the expected types, so it is
97
+ /// your responsibility that the selector exists on the receiver, and that the
98
+ /// argument types and return type are what the receiver excepts for this
99
+ /// selector - similar to defining an external function in FFI.
88
100
///
89
- /// Since this macro can't inspect header files to see the expected types, it
90
- /// is the users responsibility that the argument types and return type are
91
- /// what the receiver excepts for this selector. A way of doing this is by
92
- /// defining a wrapper function:
101
+ /// The recommended way of doing this is by defining a wrapper function:
93
102
/// ```
94
103
/// # use std::os::raw::{c_int, c_char};
95
104
/// # use objc2::msg_send;
@@ -99,19 +108,35 @@ macro_rules! sel {
99
108
/// }
100
109
/// ```
101
110
///
102
- /// The user must also uphold any safety requirements (explicit and implicit)
103
- /// that the method has (e.g. methods that take pointers as an argument
104
- /// usually require that the pointer is valid and often non-null).
111
+ /// This way we are clearly communicating to Rust that this method takes an
112
+ /// immutable object, a C-integer, and returns a pointer to (probably) a
113
+ /// C-compatible string. Afterwards, it becomes fairly trivial to make a safe
114
+ /// abstraction around this.
115
+ ///
116
+ /// In particular, you must uphold the following requirements:
117
+ ///
118
+ /// 1. The selector is a valid method that is available on the given receiver.
119
+ ///
120
+ /// 2. The types of the receiver and arguments must match what is expected on
121
+ /// the Objective-C side.
122
+ ///
123
+ /// 3. The call must not violate Rust's mutability rules, e.g. if passing an
124
+ /// `&T`, the Objective-C method must not mutate the variable (this is true
125
+ /// for receivers as well).
126
+ ///
127
+ /// 4. If the receiver is a raw pointer the user must ensure that it is valid
128
+ /// (aligned, dereferenceable, initialized and so on). Messages to `null`
129
+ /// pointers are allowed (though heavily discouraged), but only if the
130
+ /// return type itself is a pointer.
105
131
///
106
- /// Additionally, the call must not violate Rust's mutability rules, e.g. if
107
- /// passing an `&T` the Objective-C method must not mutate the variable.
132
+ /// 5. The method must not (yet, see [RFC-2945]) throw an exception.
108
133
///
109
- /// If the receiver is a raw pointer the user must ensure that it is valid
110
- /// (aligned, dereferenceable, initialized and so on). Messages to `null`
111
- /// pointers are allowed (though discouraged), but only if the return type
112
- /// itself is a pointer .
134
+ /// 6. You must uphold any additional safety requirements (explicit and
135
+ /// implicit) that the method has (for example, methods that take pointers
136
+ /// usually require that the pointer is valid, and sometimes non-null.
137
+ /// Another example, some methods may only be called on the main thread) .
113
138
///
114
- /// Finally, the method must not (yet, see [RFC-2945]) throw an exception.
139
+ /// 7. TODO: Maybe more?
115
140
///
116
141
/// # Examples
117
142
///
@@ -132,7 +157,7 @@ macro_rules! msg_send {
132
157
[ super ( $obj: expr, $superclass: expr) , $selector: ident $( , ) ?] => ( {
133
158
let sel = $crate:: sel!( $selector) ;
134
159
let result;
135
- match $crate:: MessageReceiver :: send_super_message( & $obj, $superclass, sel, ( ) ) {
160
+ match $crate:: MessageReceiver :: send_super_message( $obj, $superclass, sel, ( ) ) {
136
161
Err ( s) => panic!( "{}" , s) ,
137
162
Ok ( r) => result = r,
138
163
}
@@ -141,7 +166,7 @@ macro_rules! msg_send {
141
166
[ super ( $obj: expr, $superclass: expr) , $( $selector: ident : $argument: expr $( , ) ?) +] => ( {
142
167
let sel = $crate:: sel!( $( $selector : ) +) ;
143
168
let result;
144
- match $crate:: MessageReceiver :: send_super_message( & $obj, $superclass, sel, ( $( $argument, ) +) ) {
169
+ match $crate:: MessageReceiver :: send_super_message( $obj, $superclass, sel, ( $( $argument, ) +) ) {
145
170
Err ( s) => panic!( "{}" , s) ,
146
171
Ok ( r) => result = r,
147
172
}
@@ -150,7 +175,7 @@ macro_rules! msg_send {
150
175
[ $obj: expr, $selector: ident $( , ) ?] => ( {
151
176
let sel = $crate:: sel!( $selector) ;
152
177
let result;
153
- match $crate:: MessageReceiver :: send_message( & $obj, sel, ( ) ) {
178
+ match $crate:: MessageReceiver :: send_message( $obj, sel, ( ) ) {
154
179
Err ( s) => panic!( "{}" , s) ,
155
180
Ok ( r) => result = r,
156
181
}
@@ -159,7 +184,7 @@ macro_rules! msg_send {
159
184
[ $obj: expr, $( $selector: ident : $argument: expr $( , ) ?) +] => ( {
160
185
let sel = $crate:: sel!( $( $selector : ) +) ;
161
186
let result;
162
- match $crate:: MessageReceiver :: send_message( & $obj, sel, ( $( $argument, ) +) ) {
187
+ match $crate:: MessageReceiver :: send_message( $obj, sel, ( $( $argument, ) +) ) {
163
188
Err ( s) => panic!( "{}" , s) ,
164
189
Ok ( r) => result = r,
165
190
}
0 commit comments