@@ -72,7 +72,8 @@ impl fmt::Display for VerificationError {
72
72
impl Error for VerificationError { }
73
73
74
74
/// Relaxed version of `Encoding::equivalent_to_box` that allows
75
- /// `*mut c_void` and `*const c_void` to be used in place of other pointers.
75
+ /// `*mut c_void` and `*const c_void` to be used in place of other pointers,
76
+ /// and allows signed types where unsigned types are excepted.
76
77
///
77
78
/// Note: This is a top-level comparison; `*mut *mut c_void` or structures
78
79
/// containing `*mut c_void` are not allowed differently than usual.
@@ -81,10 +82,32 @@ fn relaxed_equivalent_to_box(encoding: &Encoding, expected: &EncodingBox) -> boo
81
82
&& matches ! ( encoding, Encoding :: Pointer ( & Encoding :: Void ) )
82
83
&& matches ! ( expected, EncodingBox :: Pointer ( _) )
83
84
{
84
- true
85
- } else {
86
- encoding. equivalent_to_box ( expected)
85
+ return true ;
87
86
}
87
+
88
+ if cfg ! ( feature = "relax-sign-encoding" ) {
89
+ let actual_signed = match encoding {
90
+ Encoding :: UChar => & Encoding :: Char ,
91
+ Encoding :: UShort => & Encoding :: Short ,
92
+ Encoding :: UInt => & Encoding :: Int ,
93
+ Encoding :: ULong => & Encoding :: Long ,
94
+ Encoding :: ULongLong => & Encoding :: LongLong ,
95
+ enc => enc,
96
+ } ;
97
+ let expected_signed = match expected {
98
+ EncodingBox :: UChar => & EncodingBox :: Char ,
99
+ EncodingBox :: UShort => & EncodingBox :: Short ,
100
+ EncodingBox :: UInt => & EncodingBox :: Int ,
101
+ EncodingBox :: ULong => & EncodingBox :: Long ,
102
+ EncodingBox :: ULongLong => & EncodingBox :: LongLong ,
103
+ enc => enc,
104
+ } ;
105
+ if actual_signed == expected_signed {
106
+ return true ;
107
+ }
108
+ }
109
+
110
+ encoding. equivalent_to_box ( expected)
88
111
}
89
112
90
113
pub ( crate ) fn verify_method_signature (
@@ -133,6 +156,7 @@ pub(crate) fn verify_method_signature(
133
156
#[ cfg( test) ]
134
157
mod tests {
135
158
use super :: * ;
159
+ use crate :: ffi;
136
160
use crate :: runtime:: Sel ;
137
161
use crate :: test_utils;
138
162
use crate :: { msg_send, sel} ;
@@ -183,6 +207,17 @@ mod tests {
183
207
"expected argument at index 0 to have type code 'I', but found ':'"
184
208
) ;
185
209
210
+ // <https://github.com/madsmtm/objc2/issues/566>
211
+ let res = cls. verify_sel :: < ( ) , ffi:: NSUInteger > ( sel ! ( getNSInteger) ) ;
212
+ let expected = if cfg ! ( feature = "relax-sign-encoding" ) {
213
+ Ok ( ( ) )
214
+ } else if cfg ! ( target_pointer_width = "64" ) {
215
+ Err ( "expected return to have type code 'q', but found 'Q'" . to_string ( ) )
216
+ } else {
217
+ Err ( "expected return to have type code 'i', but found 'I'" . to_string ( ) )
218
+ } ;
219
+ assert_eq ! ( res. map_err( |e| e. to_string( ) ) , expected) ;
220
+
186
221
// Metaclass
187
222
let metaclass = cls. metaclass ( ) ;
188
223
let err = metaclass
@@ -193,10 +228,10 @@ mod tests {
193
228
194
229
#[ test]
195
230
#[ cfg( debug_assertions) ]
196
- #[ should_panic = "invalid message send to -[CustomObject foo]: expected return to have type code 'I', but found 'i'" ]
231
+ #[ should_panic = "invalid message send to -[CustomObject foo]: expected return to have type code 'I', but found '^ i'" ]
197
232
fn test_send_message_verified ( ) {
198
233
let obj = test_utils:: custom_object ( ) ;
199
- let _: i32 = unsafe { msg_send ! [ & obj, foo] } ;
234
+ let _: * const i32 = unsafe { msg_send ! [ & obj, foo] } ;
200
235
}
201
236
202
237
#[ test]
0 commit comments