nrxus / faux

Struct mocking library for Rust
https://nrxus.github.io/faux/
MIT License
411 stars 14 forks source link

Support self: Rc #21

Closed audunhalland closed 4 years ago

audunhalland commented 4 years ago

Thanks for this really cool library!

I can't get this to work:

#[faux::methods]
impl Struct {
    pub fn foo(self: Rc<Self>) {
       ...
    }
}
nrxus commented 4 years ago

arbitrary self types are not supported yet unfortunately.

Since I have personally never used that feature I did not give it much of a priority but I now see I was mistaken. I will definitely take a look!

audunhalland commented 4 years ago

I sometimes use this pattern with async methods. Rc or Arc.

nrxus commented 4 years ago

Unfortunately It seems like supporting arbitrary self types is actually pretty hard without any guarantees of soundness. I will keep this open in case I get ideas but until then only self, &self, and &mut self methods unfortunately.

audunhalland commented 4 years ago

Interesting read. So the "mock"/"parent" owns the real object by normal ownership now, so you can do & and &mut. What about: If you see a method taking Rc<Self> - then own the real data by an Rc. If you see a method taking Arc<Self> - own the real data through an Arc. If you see both, then no way to recover. If you see any of those + a &mut method, probably also no way to recover. Not sure whether this is feasible, but in my mind impls taking arbitrary self types will typically do so on all methods, and at least not mix/match with &mut self.

nrxus commented 4 years ago

Hm... if they are all Rc<Self> or Arc<Self> then it could be do-able. It would have to be a manual configuration in the #[faux::create] attribute, something like #[faux::create(receiver_type = Rc)] since it is not #[faux::methods]'s job to morph the struct, that's that #[faux::create] does. That is a pretty do-able stop gap for now as an MVP although not very ergonomic.

If we had a module level attribute this would be easier since it could scan the entire module and check all the receiver types but oh well.

Thanks for the idea! I'll mull it over some and see how I feel about it.

audunhalland commented 4 years ago

Cool, it just might work. Would it still work with non-mutable &self?

nrxus commented 4 years ago

I believe so, since Rc<Self> will deref to &self and according to the docs:

T implicitly implements all the (immutable) methods of the type U.

Where T is Rc<Self> and U is &self

nrxus commented 4 years ago

addressed in: https://github.com/nrxus/faux/commit/e3545ef3764ef97e301ca1bd3ff94f21a5e46747

Not closing until the next version it's released but feel free to take a look at the test for what will be possible.

audunhalland commented 4 years ago

Looks like it'll work very well, I'm more than happy with this 😃 Thank you!

nrxus commented 4 years ago

v0.0.4 is released with this feature :tada: