This crate provides an attribute to simplify closure captures.
```rust use std::{rc::Rc, cell::Cell, cell::RefCell};
// Expects a 'static callback
fn use_callback
fn example() { let s = Rc::new(RefCell::new(String::new())); let i = Rc::new(Cell::new(0));
// The callback captures clones of s and i
use_callback(
#[closure(clone s, clone i)]
move || {
s.replace(format!("Hello, world! {}", i.get()));
i.set(i.get() + 1);
},
);
assert_eq!(s.borrow_mut().clone(), "Hello, world! 0");
assert_eq!(i.get(), 1);
}
example(); ```
It expands to:
ignore
use_callback({
let s = s.clone(); // Clone requested by attribute
let i = i.clone(); // Clone requested by attribute
move || {
{... code to force whole captures ...}
s.replace(format!("Hello, world! {}", i.get()));
i.set(i.get() + 1);
}
});
| Syntax | Description |
| --- | --- |
| clone <ident>
| Clone the variable |
| clone mut <ident>
| Clone the variable and make it mutable |
| ref <ident>
| Take a reference to the variable |
| ref mut <ident>
| Take a mutable reference to the variable |
| move <ident>
| Move the variable into the closure |
| move mut <ident>
| Move the variable into the closure and make it mutable |
| weak <ident>
| See below |
weak
weak
uses weak pointers to help break up reference cycles. It downgrades
an Rc
or Arc
pointer (or anything which implements [Downgrade] and [Upgrade])
and captures it. The transformed closure upgrades the pointer when it is called.
If any upgrade fails, it skips executing the body and returns Default::default()
.
```rust use std::{rc::Rc, sync::Arc};
fn example() { let r = Rc::new(3); let a = Arc::new(4);
let closure = #[closure(weak r, weak a)]
move || *r * *a;
assert_eq!(closure(), 12);
}
example(); ```
This Expands to:
ignore
let closure = {
let r = ::closure_attr::Downgrade::downgrade(&r);
let a = ::closure_attr::Downgrade::downgrade(&a);
move || {
(|| {
let r = r.upgrade()?;
let a = a.upgrade()?;
Some((|| *r * *a)())
})()
.unwrap_or_default()
}
};
The capture
attribute captures whole variables. For example, this code without the attribute produces an error:
```ignore
fn send
struct SendPointer(*const ()); unsafe impl Send for SendPointer {}
fn f() { let p = SendPointer(std::ptr::null()); send( move || { p.0; }, ); } ```
text
error[E0277]: `*const ()` cannot be sent between threads safely
A workaround:
```ignore
fn f() { let p = SendPointer(std::ptr::null()); send( #[closure(move p)] move || { p.0; }, ); } ```
This is equivalent to inserting let _ = &p;
into the body of the closure.
This work is dual-licensed under MIT and Apache 2.0. You can choose between one of them if you use this work.
SPDX-License-Identifier: MIT OR Apache-2.0