@@ -45,6 +45,7 @@ to be copied once, and we can enforce this in Rust, but if Objective-C code
45
45
were to copy it twice we could have a double free.
46
46
*/
47
47
48
+ use std:: marker:: PhantomData ;
48
49
use std:: mem;
49
50
use std:: ops:: { Deref , DerefMut } ;
50
51
use std:: ptr;
@@ -69,7 +70,8 @@ macro_rules! block_args_impl {
69
70
impl <$( $t) ,* > BlockArguments for ( $( $t, ) * ) {
70
71
fn call_block<R >( self , block: & mut Block <Self , R >) -> R {
71
72
let invoke: unsafe extern fn ( * mut Block <Self , R > $( , $t) * ) -> R = unsafe {
72
- mem:: transmute( block. invoke)
73
+ let base = & * ( block as * mut _ as * mut BlockBase <Self , R >) ;
74
+ mem:: transmute( base. invoke)
73
75
} ;
74
76
let ( $( $a, ) * ) = self ;
75
77
unsafe {
@@ -94,16 +96,21 @@ block_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
94
96
block_args_impl ! ( a: A , b: B , c: C , d: D , e: E , f: F , g: G , h: H , i: I , j: J , k: K ) ;
95
97
block_args_impl ! ( a: A , b: B , c: C , d: D , e: E , f: F , g: G , h: H , i: I , j: J , k: K , l: L ) ;
96
98
97
- /// An Objective-C block that takes arguments of `A` when called and
98
- /// returns a value of `R`.
99
99
#[ repr( C ) ]
100
- pub struct Block < A , R > {
100
+ struct BlockBase < A , R > {
101
101
isa : * const Class ,
102
102
flags : c_int ,
103
103
_reserved : c_int ,
104
104
invoke : unsafe extern fn ( * mut Block < A , R > , ...) -> R ,
105
105
}
106
106
107
+ /// An Objective-C block that takes arguments of `A` when called and
108
+ /// returns a value of `R`.
109
+ #[ repr( C ) ]
110
+ pub struct Block < A , R > {
111
+ _base : PhantomData < BlockBase < A , R > > ,
112
+ }
113
+
107
114
// TODO: impl FnMut when it's possible
108
115
impl < A : BlockArguments , R > Block < A , R > where A : BlockArguments {
109
116
/// Call self with the given arguments.
@@ -172,7 +179,7 @@ concrete_block_impl!(concrete_block_invoke_args12, a: A, b: B, c: C, d: D, e: E,
172
179
/// constructed on the stack.
173
180
#[ repr( C ) ]
174
181
pub struct ConcreteBlock < A , R , F > {
175
- base : Block < A , R > ,
182
+ base : BlockBase < A , R > ,
176
183
descriptor : Box < BlockDescriptor < ConcreteBlock < A , R , F > > > ,
177
184
closure : F ,
178
185
}
@@ -194,7 +201,7 @@ impl<A, R, F> ConcreteBlock<A, R, F> {
194
201
unsafe fn with_invoke ( invoke : unsafe extern fn ( * mut Self , ...) -> R ,
195
202
closure : F ) -> Self {
196
203
ConcreteBlock {
197
- base : Block {
204
+ base : BlockBase {
198
205
isa : & _NSConcreteStackBlock,
199
206
// 1 << 25 = BLOCK_HAS_COPY_DISPOSE
200
207
flags : 1 << 25 ,
@@ -212,7 +219,7 @@ impl<A, R, F> ConcreteBlock<A, R, F> where F: 'static {
212
219
pub fn copy ( self ) -> Id < Block < A , R > > {
213
220
unsafe {
214
221
// The copy method is declared as returning an object pointer.
215
- let block: * mut Object = msg_send ! [ & self . base , copy] ;
222
+ let block: * mut Object = msg_send ! [ & * self , copy] ;
216
223
let block = block as * mut Block < A , R > ;
217
224
// At this point, our copy helper has been run so the block will
218
225
// be moved to the heap and we can forget the original block
@@ -226,7 +233,7 @@ impl<A, R, F> ConcreteBlock<A, R, F> where F: 'static {
226
233
impl < A , R , F > Clone for ConcreteBlock < A , R , F > where F : Clone {
227
234
fn clone ( & self ) -> Self {
228
235
unsafe {
229
- ConcreteBlock :: with_invoke ( mem:: transmute ( self . invoke ) ,
236
+ ConcreteBlock :: with_invoke ( mem:: transmute ( self . base . invoke ) ,
230
237
self . closure . clone ( ) )
231
238
}
232
239
}
@@ -236,13 +243,13 @@ impl<A, R, F> Deref for ConcreteBlock<A, R, F> {
236
243
type Target = Block < A , R > ;
237
244
238
245
fn deref ( & self ) -> & Block < A , R > {
239
- & self . base
246
+ unsafe { & * ( & self . base as * const _ as * const Block < A , R > ) }
240
247
}
241
248
}
242
249
243
250
impl < A , R , F > DerefMut for ConcreteBlock < A , R , F > {
244
251
fn deref_mut ( & mut self ) -> & mut Block < A , R > {
245
- & mut self . base
252
+ unsafe { & mut * ( & mut self . base as * mut _ as * mut Block < A , R > ) }
246
253
}
247
254
}
248
255
0 commit comments