Crates.io | drop_cell |
lib.rs | drop_cell |
version | 0.0.0 |
source | src |
created_at | 2022-12-17 10:42:03.969965 |
updated_at | 2022-12-17 10:42:03.969965 |
description | An alternative way of implementing `Drop` |
homepage | |
repository | |
max_upload_size | |
id | 739754 |
size | 15,060 |
An alternative way of implementing Drop
in Rust.
This library provides the defer!
macro to defer execution until the end of the stack frame.
The defer!
macro emulates Golang Defer statements.
defer!(println!("world"));
println!("hello");
return;
println!("unreachable");
Output:
hello
world
The following code won't compile.
let mut v = vec![1, 2];
defer!(assert_eq!(v, &[1, 2, 3]));
// └─ immutable borrow occurs here ──────────┐
v.push(3); // │
// └─ mutable borrow occurs here │
// │
// immutable borrow will be used at the end of the stack frame ─┘
We want to run assert_eq!(v, &[1, 2, 3])
at the end of the stack frame, but it breaks the borrowing rules.
To work around, we need to pass v
into defer!
.
let v = vec![1, 2];
// └─ consumes it ─┐
// ┌────────────┘
defer!(v => assert_eq!(v, &[1, 2, 3]));
v.push(3);
use drop_cell::defer;
use std::io::Write;
use std::sync::mpsc;
fn main() {
no_arg();
args();
bind();
}
fn no_arg() {
let (tx, rx) = mpsc::channel();
defer! {
assert_eq!(rx.recv().unwrap(), "hello");
assert_eq!(rx.recv().unwrap(), "world");
};
tx.send("hello").unwrap();
tx.send("world").unwrap();
}
fn args() {
let (v1, v2) = (vec![], vec![]);
defer! { v1, v2 =>
assert_eq!(v1, b"hello");
assert_eq!(v2, b"world");
}
write!(v1, "hello").unwrap();
write!(v2, "world").unwrap();
}
fn bind() {
let ss = vec![];
defer! { v @ Some(ss) =>
let v = v.take().unwrap();
assert_eq!(v.as_slice(), ["hello", "world"]);
}
v.as_mut().unwrap().push("hello");
v.as_mut().unwrap().push("world");
}
struct
for it.defer!
might complicate the code.