`auto_impl`: A little utility for automatically implementing traits


#1

I’ve just published an initial release for auto_impl, a nightly compiler plugin for automatically implementing a trait for some common smart pointers and closure traits.

You add an #[auto_impl(...)] attribute to a trait to have it implement for a wrapper. There’s some more detail in the readme.

Looks like:

#[auto_impl(Fn)] // <- `auto_impl` for `Fn(GetProduct) -> Result<GetProductResult, QueryError>
pub trait GetProductQuery {
    fn get_product(&self, query: GetProduct) -> Result<GetProductResult, QueryError>;
}

// Means we can return a closure as `impl GetProductQuery`
pub fn get_product_query<TStore>(store: TStore) -> impl GetProductQuery 
    where TStore: ProductStore
{
    move |query: GetProduct| {
        let ProductData { id, title, .. } = store.get(query.id)?.ok_or("not found")?.into_data();

        Ok(GetProductResult {
            id: id,
            title: title
        })
    }
}

Or:

#[auto_impl(Arc)] // <- `auto_impl` for `Arc<T: ProductStore>`
pub trait ProductStore {
    fn get(&self, id: i32) -> Result<Option<Product>, Error>;
    fn set(&self, product: Product) -> Result<(), Error>;
}

pub struct Resolver {
    product_store: Arc<InMemoryStore>,
}

impl Resolver {
    // Means we can return an `Arc<T>` as `impl ProductStore`
    pub fn product_store(&self) -> impl ProductStore {
        self.product_store.clone()
    }
}

The plugin itself doesn’t actually do a whole lot, it started life as a macro for cases where I wanted to reduce a bit of boilerplate but didn’t want to logically link some types together through a common trait. I think its use-case is fairly niche but thought it was worth throwing it out in the wild :slight_smile:

I’ve mostly been using it internally, so there are probably cases it doesn’t cover well and some obvious enhancements I haven’t needed but would be happy to explore.

Feedback is always welcome!


#2

Instead of try_iter! you could use .collect::<Result<Vec<_>, _>>() which returns Err at the first error, or Ok with a vec of all inner items when there is no Err produced by the iterator.


#3

Thanks! Yeh I should tidy that up…


#4

Fixed :wink: Thanks again for the suggestion. I didn’t actually know FromIterator was implemented for Result!