PipeDrop

Trait PipeDrop 

Source
pub trait PipeDrop: Sized {
    // Provided methods
    fn pipe_ref_drop<F, Y>(self, f: F) -> Y
       where F: FnOnce(&Self) -> Y { ... }
    fn pipe_mut_drop<F, Y>(self, f: F) -> Y
       where F: FnOnce(&mut Self) -> Y { ... }
    fn pipe_as_ref_drop<F, X, Y>(self, f: F) -> Y
       where Self: AsRef<X>,
             X: ?Sized,
             F: FnOnce(&X) -> Y { ... }
    fn pipe_as_mut_drop<F, X, Y>(self, f: F) -> Y
       where Self: AsMut<X>,
             X: ?Sized,
             F: FnOnce(&mut X) -> Y { ... }
    fn pipe_deref_drop<F, X, Y>(self, f: F) -> Y
       where Self: Deref<Target = X>,
             X: ?Sized,
             F: FnOnce(&X) -> Y { ... }
    fn pipe_deref_mut_drop<F, X, Y>(self, f: F) -> Y
       where Self: DerefMut<Target = X>,
             X: ?Sized,
             F: FnOnce(&X) -> Y { ... }
    fn pipe_borrow_drop<F, X, Y>(self, f: F) -> Y
       where Self: Borrow<X>,
             X: ?Sized,
             F: FnOnce(&X) -> Y { ... }
    fn pipe_borrow_mut_drop<F, X, Y>(self, f: F) -> Y
       where Self: BorrowMut<X>,
             X: ?Sized,
             F: FnOnce(&X) -> Y { ... }
}
Expand description

§Purpose

Sometimes it is critical to drop an object as soon as it is no longer used, even before the end of scope. For example: Dropping a MutexGuard to prevent deadlock.

The PipeDrop trait provides methods that allow you to get a reference (immutable or otherwise) to an object, do something with the reference (inside the callback function), and then drop the object.

§Exhibit A: Drop order

Given the following code which declare an object that logs its own creation and destruction:

#[derive(Debug)]
struct Object {
    id: usize,
}

impl Default for Object {
    fn default() -> Self {
        println!("create 0");
        Object { id: 0 }
    }
}

impl Drop for Object {
    fn drop(&mut self) {
        println!("drop {}", self.id)
    }
}

impl Clone for Object {
    fn clone(&self) -> Self {
        let id = self.id + 1;
        println!("create {}", id);
        Object { id }
    }
}

The following code would only drop a and b when they are out of scope:

let a = Object::default();
let b = a.clone();
let c = b.clone();
println!("-- end of scope --");

Output:

create 0
create 1
create 2
-- end of scope --
drop 2
drop 1
drop 0

In the above output, the numbers (0, 1, 2) correspond to the variables (a, b, c respectively), and the verbs (create and drop) corresponds to actions (Object::default()/Object::clone() and drop respectively).

In order to force a and b to be dropped before the end of scope, we must explicitly call drop:

let a = Object::default();
let b = a.clone();
drop(a);
let c = b.clone();
drop(b);
println!("-- end of scope --");

Output:

create 0
create 1
drop 0
create 2
drop 1
-- end of scope --
drop 2

As you can see in the output above, both drop 0 and drop 1 were called before -- end of scope --, which means that a and b were dropped before the end of scope.

However, explicitly calling drop makes our code ugly, and quite hard to fit in a dot-chain, we can fix this by using PipeDrop:

use pipe_drop::PipeDrop;
let c = Object::default() // a
    .pipe_ref_drop(Object::clone) // b
    .pipe_ref_drop(Object::clone);
println!("-- end of scope --");

Output:

create 0
create 1
drop 0
create 2
drop 1
-- end of scope --
drop 2

The above output is exactly like when we called drop explicitly!

Provided Methods§

Source

fn pipe_ref_drop<F, Y>(self, f: F) -> Y
where F: FnOnce(&Self) -> Y,

Apply f on &self and then drop self.

Source

fn pipe_mut_drop<F, Y>(self, f: F) -> Y
where F: FnOnce(&mut Self) -> Y,

Apply f on &mut self and then drop self.

Source

fn pipe_as_ref_drop<F, X, Y>(self, f: F) -> Y
where Self: AsRef<X>, X: ?Sized, F: FnOnce(&X) -> Y,

Apply f on self.as_ref() and then drop self.

Source

fn pipe_as_mut_drop<F, X, Y>(self, f: F) -> Y
where Self: AsMut<X>, X: ?Sized, F: FnOnce(&mut X) -> Y,

Apply f on self.as_mut() and then drop self.

Source

fn pipe_deref_drop<F, X, Y>(self, f: F) -> Y
where Self: Deref<Target = X>, X: ?Sized, F: FnOnce(&X) -> Y,

Apply f on &self and then drop self.

Source

fn pipe_deref_mut_drop<F, X, Y>(self, f: F) -> Y
where Self: DerefMut<Target = X>, X: ?Sized, F: FnOnce(&X) -> Y,

Apply f on &mut self and then drop self.

Source

fn pipe_borrow_drop<F, X, Y>(self, f: F) -> Y
where Self: Borrow<X>, X: ?Sized, F: FnOnce(&X) -> Y,

Apply f on self.borrow() and then drop self.

Source

fn pipe_borrow_mut_drop<F, X, Y>(self, f: F) -> Y
where Self: BorrowMut<X>, X: ?Sized, F: FnOnce(&X) -> Y,

Apply f on self.borrow_mut() and then drop self.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<X> PipeDrop for X