@@ -124,6 +124,7 @@ use std::ffi::CString;
124
124
125
125
use crate :: encode:: { Encode , EncodeArguments , Encoding , RefEncode } ;
126
126
use crate :: ffi;
127
+ use crate :: rc:: Allocated ;
127
128
use crate :: runtime:: { Bool , Class , Imp , Object , Protocol , Sel } ;
128
129
use crate :: sel;
129
130
use crate :: Message ;
@@ -196,6 +197,37 @@ macro_rules! method_decl_impl {
196
197
}
197
198
}
198
199
} ;
200
+ ( @<> Allocated <T >, $f: ty, $( $t: ident) ,* ) => {
201
+ #[ doc( hidden) ]
202
+ impl <T , $( $t) ,* > private:: Sealed for $f
203
+ where
204
+ T : Message + ?Sized ,
205
+ $( $t: Encode , ) *
206
+ { }
207
+
208
+ #[ doc( hidden) ]
209
+ impl <T , $( $t) ,* > MethodImplementation for $f
210
+ where
211
+ T : Message + ?Sized ,
212
+ $( $t: Encode , ) *
213
+ {
214
+ type Callee = T ;
215
+ type Ret = __IdReturnValue;
216
+ type Args = ( $( $t, ) * ) ;
217
+
218
+ fn __imp( self ) -> Imp {
219
+ // SAFETY: `Allocated<T>` is the same as `NonNull<T>`, except
220
+ // with the assumption of a +1 calling convention.
221
+ //
222
+ // The calling convention is ensured to be upheld by having
223
+ // `__IdReturnValue` in the type, since that type is private
224
+ // and hence only internal macros like `#[method_id]` will be
225
+ // able to produce it (and that, in turn, only allows it if
226
+ // the selector is `init` as checked by `MessageRecieveId`).
227
+ unsafe { mem:: transmute( self ) }
228
+ }
229
+ }
230
+ } ;
199
231
( # $abi: literal; $( $t: ident) ,* ) => {
200
232
method_decl_impl!( @<' a> T , R , extern $abi fn ( & ' a T , Sel $( , $t) * ) -> R , $( $t) ,* ) ;
201
233
method_decl_impl!( @<' a> T , R , extern $abi fn ( & ' a mut T , Sel $( , $t) * ) -> R , $( $t) ,* ) ;
@@ -207,6 +239,9 @@ macro_rules! method_decl_impl {
207
239
method_decl_impl!( @<' a> Class , R , extern $abi fn ( & ' a Class , Sel $( , $t) * ) -> R , $( $t) ,* ) ;
208
240
method_decl_impl!( @<> Class , R , unsafe extern $abi fn ( * const Class , Sel $( , $t) * ) -> R , $( $t) ,* ) ;
209
241
method_decl_impl!( @<' a> Class , R , unsafe extern $abi fn ( & ' a Class , Sel $( , $t) * ) -> R , $( $t) ,* ) ;
242
+
243
+ method_decl_impl!( @<> Allocated <T >, extern $abi fn ( Allocated <T >, Sel $( , $t) * ) -> __IdReturnValue, $( $t) ,* ) ;
244
+ method_decl_impl!( @<> Allocated <T >, unsafe extern $abi fn ( Allocated <T >, Sel $( , $t) * ) -> __IdReturnValue, $( $t) ,* ) ;
210
245
} ;
211
246
( $( $t: ident) ,* ) => {
212
247
method_decl_impl!( # "C" ; $( $t) ,* ) ;
@@ -229,6 +264,17 @@ method_decl_impl!(A, B, C, D, E, F, G, H, I, J);
229
264
method_decl_impl ! ( A , B , C , D , E , F , G , H , I , J , K ) ;
230
265
method_decl_impl ! ( A , B , C , D , E , F , G , H , I , J , K , L ) ;
231
266
267
+ /// Helper type for implementing `MethodImplementation` with a receiver of
268
+ /// `Allocated<T>`, without exposing that implementation to users.
269
+ #[ doc( hidden) ]
270
+ #[ repr( transparent) ]
271
+ pub struct __IdReturnValue ( pub ( crate ) * mut Object ) ;
272
+
273
+ // SAFETY: `__IdReturnValue` is `#[repr(transparent)]`
274
+ unsafe impl Encode for __IdReturnValue {
275
+ const ENCODING : Encoding = <* mut Object >:: ENCODING ;
276
+ }
277
+
232
278
fn method_type_encoding ( ret : & Encoding , args : & [ Encoding ] ) -> CString {
233
279
// First two arguments are always self and the selector
234
280
let mut types = format ! ( "{ret}{}{}" , <* mut Object >:: ENCODING , Sel :: ENCODING ) ;
@@ -630,6 +676,7 @@ impl ProtocolBuilder {
630
676
#[ cfg( test) ]
631
677
mod tests {
632
678
use super :: * ;
679
+ use crate :: rc:: { Id , Shared } ;
633
680
use crate :: runtime:: { NSObject , NSZone } ;
634
681
use crate :: test_utils;
635
682
use crate :: { declare_class, extern_protocol, msg_send, ClassType , ConformsTo , ProtocolType } ;
@@ -641,8 +688,8 @@ mod tests {
641
688
const NAME : & ' static str = "NSCopying" ;
642
689
643
690
#[ allow( unused) ]
644
- #[ method ( copyWithZone: ) ]
645
- fn copy_with_zone( & self , _zone: * const NSZone ) -> * mut Self ;
691
+ #[ method_id ( copyWithZone: ) ]
692
+ fn copy_with_zone( & self , _zone: * const NSZone ) -> Id < Self , Shared > ;
646
693
}
647
694
) ;
648
695
@@ -814,9 +861,8 @@ mod tests {
814
861
}
815
862
816
863
unsafe impl ConformsTo <NSCopyingObject > for Custom {
817
- #[ method( copyWithZone: ) ]
818
- #[ allow( unreachable_code) ]
819
- fn copy_with_zone( & self , _zone: * const NSZone ) -> * mut Self {
864
+ #[ method_id( copyWithZone: ) ]
865
+ fn copy_with_zone( & self , _zone: * const NSZone ) -> Id <Self , Shared > {
820
866
unimplemented!( )
821
867
}
822
868
}
@@ -910,9 +956,8 @@ mod tests {
910
956
}
911
957
912
958
unsafe impl ConformsTo <NSCopyingObject > for Custom {
913
- #[ method( copyWithZone: ) ]
914
- #[ allow( unreachable_code) ]
915
- fn copy_with_zone( & self , _zone: * const NSZone ) -> * mut Self {
959
+ #[ method_id( copyWithZone: ) ]
960
+ fn copy_with_zone( & self , _zone: * const NSZone ) -> Id <Self , Shared > {
916
961
unimplemented!( )
917
962
}
918
963
0 commit comments