Add a new trait Consume<S, T>::consume(self) -> Consumed<S, T>

Motivation

In case when user want to unwrap value from some safe wrapping:

// Let's assume that Jimmy is any sized type
let wrapped = Arc::new(Jimmy::new());

let desired: Jimmy = todo!();  //  <- How to get Jimmy out there?

// We know that is NOT always possible, but such cases DOES exist
// But, in this case we can impl Consume<Arc<T>, T> for Arc
let actual: Consumed<Jimmy, Arc<Jimmy>> = Consume::consume(wrapped);

match actual {
    // May be even result?
    Consumed::Fail(wrapped) => { /* Jimmy is busy, but it's okay */ },
    Consumed::Value(jimmy) => { /* Jimmy is real and can be passed somewhere */ }
}

Other possible consumes:

  • RwLock, Rc, Arc, Mutex (maybe others?) for T
  • Previous ones but for Box<T: ?Sized> to allow consume Rc<dyn Trait> as Box<dyn Trait> (maybe implement Rc to RwLock and other variations?)

Note: This is just a scratch and for now I don't know what to add to this post, but any notes, suggestions, tips and others, are welcome!

Isn't this just Arc::try_unwrap and Rc::try_unwrap? What benefits does an additional trait bring?

2 Likes

I was trying to implement Arc to Box for objects, but it doesn't work due to bounds from Result? If I understand correctly.

Such a new trait and it's struct will allow to relax bounds + provides a general way to consume self (context related, like Into, AsRef and other, I suppose)

Specifically, because you can't directly have a value of type dyn Trait without some sort of indirection, because it's not Sized and as thus you don't know how much stack space you need to have available for it.

std could implement TryFrom<Arc<R>> for Box<T> for unsized T. In fact, since you've stated you want Consume::consume to be able to return Box<T>, it's exactly the same signature as TryFrom::try_from.

That's probably the (unexposed) trait for method receivers, which defines the set of types which can be used for methods.

Generally, when proposing a trait it's good practice to actually show a potential definition of the trait, instead of just use of the trait. Among other things, this helps to clarify just how generic the trait is intended to be.

Thanks for advice. So, for now I need something like you said:

impl TryFrom<Arc<T>> for Box<T> {
    type Error = Arc<T>;

    fn try_from(this: Self) -> Result<Self, Self::Error> {
        if this.inner().strong.compare_exchange(1, 0, Relaxed, Relaxed).is_err() {
            return Err(this);
        }

        acquire!(this.inner().strong);

        unsafe {
            /* MAGIC */
        }
    }
}

But for any containers (e.g. RwLock)

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.