@@ -13,26 +13,34 @@ mod argument_private {
13
13
/// Objective-C `BOOL`, where it would otherwise not be allowed (since they
14
14
/// are not ABI compatible).
15
15
///
16
- /// This is also done specially for `&mut Retained<_>`-like arguments, to allow
17
- /// using those as "out" parameters.
16
+ /// This is also done specially for `&mut Retained<_>`-like arguments, to
17
+ /// allow using those as "out" / pass-by-writeback parameters.
18
18
pub trait ConvertArgument : argument_private:: Sealed {
19
19
/// The inner type that this can be converted to and from.
20
20
#[ doc( hidden) ]
21
21
type __Inner : EncodeArgument ;
22
22
23
23
/// A helper type for out parameters.
24
+ ///
25
+ /// When dropped, this will process any necessary change to the
26
+ /// parameters.
24
27
#[ doc( hidden) ]
25
- type __StoredBeforeMessage : Sized ;
28
+ type __WritebackOnDrop : Sized ;
26
29
27
30
#[ doc( hidden) ]
28
31
fn __from_defined_param ( inner : Self :: __Inner ) -> Self ;
29
32
33
+ /// # Safety
34
+ ///
35
+ /// The `__WritebackOnDrop` return type must not be leaked, and the
36
+ /// `__Inner` pointer must not be used after the `__WritebackOnDrop` has
37
+ /// dropped.
38
+ ///
39
+ /// NOTE: The standard way to ensure such a thing is with closures, but
40
+ /// using those would interact poorly with backtraces of the message send,
41
+ /// so we're forced to ensure this out of band.
30
42
#[ doc( hidden) ]
31
- fn __into_argument ( self ) -> ( Self :: __Inner , Self :: __StoredBeforeMessage ) ;
32
-
33
- #[ doc( hidden) ]
34
- #[ inline]
35
- unsafe fn __process_after_message_send ( _stored : Self :: __StoredBeforeMessage ) { }
43
+ unsafe fn __into_argument ( self ) -> ( Self :: __Inner , Self :: __WritebackOnDrop ) ;
36
44
}
37
45
38
46
// Implemented in writeback.rs
@@ -45,15 +53,15 @@ impl<T: EncodeArgument> argument_private::Sealed for T {}
45
53
impl < T : EncodeArgument > ConvertArgument for T {
46
54
type __Inner = Self ;
47
55
48
- type __StoredBeforeMessage = ( ) ;
56
+ type __WritebackOnDrop = ( ) ;
49
57
50
58
#[ inline]
51
59
fn __from_defined_param ( inner : Self :: __Inner ) -> Self {
52
60
inner
53
61
}
54
62
55
63
#[ inline]
56
- fn __into_argument ( self ) -> ( Self :: __Inner , Self :: __StoredBeforeMessage ) {
64
+ unsafe fn __into_argument ( self ) -> ( Self :: __Inner , Self :: __WritebackOnDrop ) {
57
65
( self , ( ) )
58
66
}
59
67
}
@@ -62,15 +70,15 @@ impl argument_private::Sealed for bool {}
62
70
impl ConvertArgument for bool {
63
71
type __Inner = Bool ;
64
72
65
- type __StoredBeforeMessage = ( ) ;
73
+ type __WritebackOnDrop = ( ) ;
66
74
67
75
#[ inline]
68
76
fn __from_defined_param ( inner : Self :: __Inner ) -> Self {
69
77
inner. as_bool ( )
70
78
}
71
79
72
80
#[ inline]
73
- fn __into_argument ( self ) -> ( Self :: __Inner , Self :: __StoredBeforeMessage ) {
81
+ unsafe fn __into_argument ( self ) -> ( Self :: __Inner , Self :: __WritebackOnDrop ) {
74
82
( Bool :: new ( self ) , ( ) )
75
83
}
76
84
}
@@ -127,13 +135,10 @@ pub trait ConvertArguments {
127
135
type __Inner : EncodeArguments ;
128
136
129
137
#[ doc( hidden) ]
130
- type __StoredBeforeMessage : Sized ;
131
-
132
- #[ doc( hidden) ]
133
- fn __into_arguments ( self ) -> ( Self :: __Inner , Self :: __StoredBeforeMessage ) ;
138
+ type __WritebackOnDrop : Sized ;
134
139
135
140
#[ doc( hidden) ]
136
- unsafe fn __process_after_message_send ( _stored : Self :: __StoredBeforeMessage ) ;
141
+ unsafe fn __into_arguments ( self ) -> ( Self :: __Inner , Self :: __WritebackOnDrop ) ;
137
142
}
138
143
139
144
pub trait TupleExtender < T > {
@@ -148,22 +153,16 @@ macro_rules! args_impl {
148
153
impl <$( $t: ConvertArgument ) ,* > ConvertArguments for ( $( $t, ) * ) {
149
154
type __Inner = ( $( $t:: __Inner, ) * ) ;
150
155
151
- type __StoredBeforeMessage = ( $( $t:: __StoredBeforeMessage , ) * ) ;
156
+ type __WritebackOnDrop = ( $( $t:: __WritebackOnDrop , ) * ) ;
152
157
153
158
#[ inline]
154
- fn __into_arguments( self ) -> ( Self :: __Inner, Self :: __StoredBeforeMessage ) {
159
+ unsafe fn __into_arguments( self ) -> ( Self :: __Inner, Self :: __WritebackOnDrop ) {
155
160
let ( $( $a, ) * ) = self ;
156
- $( let $a = ConvertArgument :: __into_argument( $a) ; ) *
161
+ // SAFETY: Upheld by caller
162
+ $( let $a = unsafe { ConvertArgument :: __into_argument( $a) } ; ) *
157
163
158
164
( ( $( $a. 0 , ) * ) , ( $( $a. 1 , ) * ) )
159
165
}
160
-
161
- #[ inline]
162
- unsafe fn __process_after_message_send( ( $( $a, ) * ) : Self :: __StoredBeforeMessage) {
163
- $(
164
- unsafe { <$t as ConvertArgument >:: __process_after_message_send( $a) } ;
165
- ) *
166
- }
167
166
}
168
167
169
168
impl <$( $t, ) * T > TupleExtender <T > for ( $( $t, ) * ) {
@@ -296,7 +295,7 @@ mod tests {
296
295
TypeId :: of:: <i32 >( )
297
296
) ;
298
297
assert_eq ! ( <i32 as ConvertArgument >:: __from_defined_param( 42 ) , 42 ) ;
299
- assert_eq ! ( ConvertArgument :: __into_argument( 42i32 ) . 0 , 42 ) ;
298
+ assert_eq ! ( unsafe { ConvertArgument :: __into_argument( 42i32 ) . 0 } , 42 ) ;
300
299
}
301
300
302
301
#[ test]
@@ -306,7 +305,7 @@ mod tests {
306
305
TypeId :: of:: <i8 >( )
307
306
) ;
308
307
assert_eq ! ( <i8 as ConvertArgument >:: __from_defined_param( -3 ) , -3 ) ;
309
- assert_eq ! ( ConvertArgument :: __into_argument( -3i32 ) . 0 , -3 ) ;
308
+ assert_eq ! ( unsafe { ConvertArgument :: __into_argument( -3i32 ) . 0 } , -3 ) ;
310
309
}
311
310
312
311
#[ test]
@@ -316,8 +315,8 @@ mod tests {
316
315
assert ! ( !<bool as ConvertReturn >:: __from_return( Bool :: NO ) ) ;
317
316
assert ! ( <bool as ConvertReturn >:: __from_return( Bool :: YES ) ) ;
318
317
319
- assert ! ( !ConvertArgument :: __into_argument( false ) . 0 . as_bool( ) ) ;
320
- assert ! ( ConvertArgument :: __into_argument( true ) . 0 . as_bool( ) ) ;
318
+ assert ! ( !unsafe { ConvertArgument :: __into_argument( false ) . 0 } . as_bool( ) ) ;
319
+ assert ! ( unsafe { ConvertArgument :: __into_argument( true ) . 0 } . as_bool( ) ) ;
321
320
assert ! ( !ConvertReturn :: __into_defined_return( false ) . as_bool( ) ) ;
322
321
assert ! ( ConvertReturn :: __into_defined_return( true ) . as_bool( ) ) ;
323
322
0 commit comments