Question

I'w writing a program in Rust that basically pushes data through a pipeline of steps that transforms it in different ways. The data is represented by an Entry, and I am designing a Step trait for the steps in the pipeline.

The trait should have a method that process the entry. My first design was this:

fn process(&self, entry: &mut Entry) -> ()

Later, I realize I wanted some steps to be able to drop the entry, i.e. somehow signal to the caller that the entry should not be processed any further through the pipeline. I am considering two different signatures for this:

fn process(&self, entry: Entry) -> Option<Entry> //Returns None if object is dropped.
fn process(&self, entry: &mut Entry) -> bool  //Returns false if object is dropped.

Which one would you say is the most idiomatic and cleanest? Is there any performance penalty in passing the ownership around as in the first option? Is there a third better alternative?

Was it helpful?

Solution

Although the Drop trait's drop() method is declared with &mut self, it is not actually possible to call that method directly. Instead you would have to use std::mem::drop() which takes ownership of the object.

This makes sense: once a value has been dropped it no longer exists in an initialized state. Accessing it afterwards would effectively be undefined behaviour, but that is exactly what Rust's lifetime system tries to prevent. Rust won't drop an object that is still owned.

This leaves your fn process(entry: Entry) -> Option<Entry> as the only declaration that will work, and would also be the safest option if there was a choice. Note that this means you won't have to drop explicitly: simply returning None instead of Some(entry) will implicitly drop the entry.

Moving ownership of an object might imply a tiny performance cost because this usually requires a shallow copy (like a move-constructor in C++, or a memcpy() in C). This is not an issue for most objects unless they are large structs. If you are concerned about this, use a Box<Entry> instead, which simply adds some pointer indirection to avoid moves.

Licensed under: CC-BY-SA with attribution
scroll top