Recursive From for reference on tuple Single< T >( T )?

There is a trick to define recursive From for reference. Like that:

impl<T> From<&T> for Single
where
    T: Clone,
    Self: From<T>,
{
    fn from(src: &T) -> Self {
        From::from((*src).clone())
    }
}

Playground

Problem is that trick does not work if the element of the tuple is a parameter:

struct Single< E >( E );

The reason is conflicting implementation. The best I've got is:

impl<E> From<&E> for Single<E>
where
    E: Clone,
    Self: From<E>,
{
    fn from(src: &E) -> Self {
        From::from((*src).clone())
    }
}

Playground

The limitation of the solution is that it does not allow to get From working for deep reference. That does not work:

let a : Single< i32 > = Single::from( &&13 )

It is a minor limitation, but I am curious is it possible to overcome it?

Probably, not.

You can just write that as From::from(src.clone()) or even src.clone().into(). It will find the same receiver. Speaking of which, this is a looser restriction (which may not really matter here [1]):

impl<T> From<&T> for Single
where
    T: Clone + Into<Self>,
{
    fn from(src: &T) -> Self {
        src.clone().into()
    }
}

I can't think of a way to have both both generic implementations without overlapping.


  1. it used to matter more when the orphan rules were more strict ↩ī¸Ž

1 Like

Thanks, but that does not work for let a: Single<i32> = Single::from(&&&13):

error[E0277]: the trait bound `Single<i32>: From<&&&{integer}>` is not satisfied
  --> src/main.rs:36:26
   |
36 |     let a: Single<i32> = Single::from(&&&13);
   |                          ^^^^^^^^^^^^ the trait `From<&&&{integer}>` is not implemented for `Single<i32>`
   |
   = help: the following implementations were found:
             <Single<E> as From<E>>
             <Single<T> as From<&T>>

Playground

Oh, sorry -- I don't have a solution to your OP, and the rest of my comment was just sort of a drive-by comment. Here's what I percieved your general version to be:

impl<T, E> From<&T> for Single<E>
where
    T: Clone + Into<Self>,
{
    fn from(src: &T) -> Self {
        src.clone().into()
    }
}

You can comment out the From<i32> version in place of the From<E> version to see it works with concrete From implementations but not the generic one (as the generic one includes all references too). I don't think there's a way around this.

In your latest playground:

impl<T> From<&T> for Single<T>
// ...

By definition this can only remove a single reference layer; you're going from &T to T (along with the latter being inside a Single).

1 Like

Aha! I thought so. Thanks for advises.

What is possible to do:

impl<E> From<&E> for Single<E>
impl<E> From<&&E> for Single<E>
impl<E> From<&&&E> for Single<E>

Although it's not recursive.

1 Like