Kimundi / owning-ref-rs

A library for creating references that carry their owner with them.
MIT License
359 stars 50 forks source link

OwningHandle equivalent for dependent mutable objects #22

Open jonhoo opened 7 years ago

jonhoo commented 7 years ago

OwningHandle currently passes a *const O::Target to the closure passed to new. Because of this, it is not possible to create handles whose inner object depends on a mutable reference to its ancestor object. For a more concrete example, consider:

struct Foo;
struct Bar<'a> { foo: &'a mut Foo };
impl Foo { fn bar<'a>(&'a mut self) -> Bar<'a> { Bar{self} }

fn main() {
  use owning_ref::OwningHandle;
  let handle = OwningHandle(Box::new(Foo), |foo| unsafe{&mut *foo}.bar());
}

Now, obviously, this couldn't be fixed just by giving the closure a *mut O::Target, since we'd then potentially run into trouble given that the handle still implements Deref, whereas the inner object may continue to depend on having exclusive access to the outer object. It's almost as though we want this kind of mutable owning handle to only implement DerefMut, though I don't know if there is even a way of doing that?

The concrete use-case I have that needs this (I think) is as follows: I have a thread that at some point receives a factory-like object on a channel in its main loop. When it does, it needs to use that factory to create a new thing from that factory, which it will then use in later invocations. Crucially, the factory is a "one-at-a-time" factory, so it has a signature of fn make<'a>(&'a mut self) -> Useful<'a>, so I can't use OwningHandle in its current form. However, the thread does own the factory, so it should be possible to construct an owning mutable handle in the manner described above.

Another use-case that might fit well with this is RefCell and RefMut. You could construct an owning mutable handle that holds a RefCell and its derived RefMut.

Is this something that might be considered as an addition to owning-ref?

Kimundi commented 7 years ago

Hi, I'm sincerely sorry for taking so long to respond.

I just merged https://github.com/Kimundi/owning-ref-rs/pull/17, which enables the usecase for giving mutable access to the internal mutability handles like RefCell.

I'd certainly consider further additions in this regard! The API grew enough with the last few merges that I think a whole refactor of the crate is in order anyway.

Storyyeller commented 7 years ago

I noticed that the new code uses StableAddress for both immutable and mutable owned references. I was wondering whether it would make sense to use separate traits, since you might have a type where Deref is stable but DerefMut is not.

As a concrete example, my easy_strings library uses copy on write internally, so EZString is stable under deref(), but calling deref_mut() will reallocate the internal buffer.

Kimundi commented 7 years ago

Hm, interesting.

I think rather than supporting that usecase natively by introducing more traits, it might be simpler to define a Deref-only implementing wrapper type for EZString that implements StableAddress