implement trait for owned and borrowed

Viewed 1014

I have the following rust snippet:

trait Foo { 
    fn foo(&self); 
}

struct FooImpl;

impl Foo for FooImpl { 
    fn foo(&self) {} 
}

fn do_foo(foo_doer: impl Foo) { 
    foo_doer.foo()
}

this line works:

do_foo(FooImpl {});

but when I try to run this:

do_foo(&FooImpl {});

I understandably get error: the trait bound &FooImpl: Foo is not satisfied.

I can obviously do this:

impl Foo for &FooImpl { fn foo(&self) {} }

and then it will work, but I'd have to do this for multiple types and I'd have to copy some code each time. Additionally in my case I can only get not only a borrow but a mutable borrow. Which means I have to impl it for &mut FooImpl, and sometimes I'd like to run it from an immutable borrow of the mutable borrow meaning I have to implement it for &&mut FooImpl, you get the idea.

My question is whether there is some trait impl / generic trickery you can recommend that will allow me to impl a trait for both owned instances and borrowed instances?

Alternatively can I change something on the do_foo function side that will allow it to accept both types of instances?

I have read Do I have to implement a trait twice when implementing it for both reference and non-reference types? and it works on my toy program. But my problem is the trait I am trying to impl in my actual code is from a different crate, so the compiler does will not allow me to impl Borrow<FooImpl> on that trait I think due to orphan rules (error: type parameter B must be used as the type parameter for some local type). Is there a solution that works around the orphan rules?

1 Answers

My question is whether there is some trait impl / generic trickery you can recommend that will allow me to impl a trait for both owned instances and borrowed instances?

You might be able to use Borrow/AsRef.

sometimes I'd like to run it from an immutable borrow of the mutable borrow meaning I have to implement it for &&mut FooImpl, you get the idea.

Just reborrow to get either an &FooImpl?

Related