Skip to content

Commit 8f863bd

Browse files
committed
Add library support for destructible lambdas
1 parent 99da9cc commit 8f863bd

2 files changed

Lines changed: 58 additions & 9 deletions

File tree

‎libcc2rs-macros/src/lambda.rs‎

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ struct Lambda {
1818
closure: ExprClosure,
1919
copy_from: Option<CaptureInits>,
2020
move_from: Option<CaptureInits>,
21+
destroy: Option<proc_macro2::TokenStream>,
2122
}
2223

2324
impl Parse for Lambda {
@@ -28,19 +29,24 @@ impl Parse for Lambda {
2829
input.parse::<Option<Token![,]>>()?;
2930
let mut copy_from = None;
3031
let mut move_from = None;
32+
let mut destroy = None;
3133
while !input.is_empty() {
3234
let name: Ident = input.parse()?;
33-
let inits;
34-
braced!(inits in input);
35-
let inits = inits.parse_terminated(FieldValue::parse, Token![,])?;
35+
if name == "destroy" {
36+
input.parse::<Token![=]>()?;
37+
}
38+
let body;
39+
braced!(body in input);
3640
if name == "copy_from" {
37-
copy_from = Some(inits);
41+
copy_from = Some(body.parse_terminated(FieldValue::parse, Token![,])?);
3842
} else if name == "move_from" {
39-
move_from = Some(inits);
43+
move_from = Some(body.parse_terminated(FieldValue::parse, Token![,])?);
44+
} else if name == "destroy" {
45+
destroy = Some(body.parse()?);
4046
} else {
4147
return Err(Error::new(
4248
name.span(),
43-
"expected `copy_from` or `move_from`",
49+
"expected `copy_from`, `move_from` or `destroy`",
4450
));
4551
}
4652
input.parse::<Option<Token![,]>>()?;
@@ -50,6 +56,7 @@ impl Parse for Lambda {
5056
closure,
5157
copy_from,
5258
move_from,
59+
destroy,
5360
})
5461
}
5562
}
@@ -207,14 +214,21 @@ fn expand_lambda(lambda: Lambda, is_unsafe: bool) -> Result<proc_macro2::TokenSt
207214
let body = rewrite_captures(quote! { #body }, &captured, false)?;
208215
let copy_from = expand_constructor(&lambda.copy_from, &captured, is_unsafe)?;
209216
let move_from = expand_constructor(&lambda.move_from, &captured, is_unsafe)?;
210-
let (receiver, body, constructor) = if is_unsafe {
217+
let destroy = &lambda.destroy;
218+
let (receiver, body, destroy, constructor) = if is_unsafe {
211219
(
212220
quote! { &mut self },
213221
quote! { unsafe { #body } },
222+
quote! { unsafe { #destroy } },
214223
quote! { from_lambda_unsafe },
215224
)
216225
} else {
217-
(quote! { &self }, body, quote! { from_lambda })
226+
(
227+
quote! { &self },
228+
body,
229+
quote! { #destroy },
230+
quote! { from_lambda },
231+
)
218232
};
219233

220234
Ok(quote! {{
@@ -234,12 +248,17 @@ fn expand_lambda(lambda: Lambda, is_unsafe: bool) -> Result<proc_macro2::TokenSt
234248
fn move_from(#receiver) -> Self {
235249
#move_from
236250
}
251+
#[allow(unused_unsafe)]
252+
fn destroy(#receiver) {
253+
#destroy
254+
}
237255
}
238256
::libcc2rs::FnPtr::<fn(#(#param_types),*) #output>::#constructor(
239257
__Lambda { #(#names: #inits,)* },
240258
__Lambda::call,
241259
__Lambda::copy_from,
242260
__Lambda::move_from,
261+
__Lambda::destroy,
243262
)
244263
}})
245264
}

‎libcc2rs/src/fn_ptr.rs‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ trait Adapted: Any {
5858
fn move_from(&self) -> Option<Rc<dyn Adapted>> {
5959
None
6060
}
61+
62+
fn destroy(&self) {}
6163
}
6264

6365
impl<T: FnSig> Adapted for T {
@@ -72,20 +74,23 @@ trait Lambda<T: FnSig> {
7274
fn call(&self, args: T::Args) -> T::Ret;
7375
fn copy_from(&self) -> Box<dyn Lambda<T>>;
7476
fn move_from(&self) -> Box<dyn Lambda<T>>;
77+
fn destroy(&self);
7578
}
7679

7780
struct LambdaSafe<L, C> {
7881
captures: L,
7982
call: C,
8083
copy_from: fn(&L) -> L,
8184
move_from: fn(&L) -> L,
85+
destroy: fn(&L),
8286
}
8387

8488
struct LambdaUnsafe<L, C> {
8589
captures: UnsafeCell<L>,
8690
call: C,
8791
copy_from: fn(&mut L) -> L,
8892
move_from: fn(&mut L) -> L,
93+
destroy: fn(&mut L),
8994
}
9095

9196
struct Closure<T: FnSig>(Box<dyn Lambda<T>>);
@@ -104,6 +109,10 @@ impl<T: FnSig> Adapted for Closure<T> {
104109
fn move_from(&self) -> Option<Rc<dyn Adapted>> {
105110
Some(Rc::new(Closure::<T>(self.0.move_from())))
106111
}
112+
113+
fn destroy(&self) {
114+
self.0.destroy();
115+
}
107116
}
108117

109118
pub struct FnPtr<T: FnSig> {
@@ -225,6 +234,12 @@ impl<T: FnSig> FnPtr<T> {
225234
}
226235
}
227236

237+
pub fn destroy(&self) {
238+
if let Some(original) = &self.original {
239+
original.destroy();
240+
}
241+
}
242+
228243
fn boxed_original(&self) -> Option<Rc<dyn Adapted>> {
229244
match &self.original {
230245
Some(original) => Some(original.clone()),
@@ -254,8 +269,9 @@ macro_rules! impl_fn_ptr_call {
254269
call: fn(&Captures $(, $a)*) -> R,
255270
copy_from: fn(&Captures) -> Captures,
256271
move_from: fn(&Captures) -> Captures,
272+
destroy: fn(&Captures),
257273
) -> Self {
258-
let lambda = LambdaSafe { captures, call, copy_from, move_from };
274+
let lambda = LambdaSafe { captures, call, copy_from, move_from, destroy };
259275
FnPtr {
260276
addr: call as usize,
261277
current: None,
@@ -268,12 +284,14 @@ macro_rules! impl_fn_ptr_call {
268284
call: fn(&mut Captures $(, $a)*) -> R,
269285
copy_from: fn(&mut Captures) -> Captures,
270286
move_from: fn(&mut Captures) -> Captures,
287+
destroy: fn(&mut Captures),
271288
) -> Self {
272289
let lambda = LambdaUnsafe {
273290
captures: UnsafeCell::new(captures),
274291
call,
275292
copy_from,
276293
move_from,
294+
destroy,
277295
};
278296
FnPtr {
279297
addr: call as usize,
@@ -297,6 +315,7 @@ macro_rules! impl_fn_ptr_call {
297315
call: self.call,
298316
copy_from: self.copy_from,
299317
move_from: self.move_from,
318+
destroy: self.destroy,
300319
})
301320
}
302321

@@ -306,8 +325,13 @@ macro_rules! impl_fn_ptr_call {
306325
call: self.call,
307326
copy_from: self.copy_from,
308327
move_from: self.move_from,
328+
destroy: self.destroy,
309329
})
310330
}
331+
332+
fn destroy(&self) {
333+
(self.destroy)(&self.captures)
334+
}
311335
}
312336

313337
impl<Captures: 'static, R: FnPtrArg $(, $a: FnPtrArg)*> Lambda<fn($($a,)*) -> R>
@@ -326,6 +350,7 @@ macro_rules! impl_fn_ptr_call {
326350
call: self.call,
327351
copy_from: self.copy_from,
328352
move_from: self.move_from,
353+
destroy: self.destroy,
329354
})
330355
}
331356

@@ -337,8 +362,13 @@ macro_rules! impl_fn_ptr_call {
337362
call: self.call,
338363
copy_from: self.copy_from,
339364
move_from: self.move_from,
365+
destroy: self.destroy,
340366
})
341367
}
368+
369+
fn destroy(&self) {
370+
(self.destroy)(unsafe { &mut *self.captures.get() })
371+
}
342372
}
343373
impl_fn_ptr_call!(@peel $($a)*);
344374
};

0 commit comments

Comments
 (0)