From<&'r {integer}> impls

I just noticed that there are no for<'r> {integer}: From<&'r {integer}> implementations. I encountered this recently when writing code that is generic over number types, some of which are !Copy and wanting to avoid cloning in between.

It seems like there is only one sensible implementation, namely to do a simple |x: &{integer}| *x.

Is this something that would make sense to implement?

This is basically the exact signature and functionality of Clone::clone. Given you say you're working with some !Copy types, if they also provide this From impl it'll be by cloning.

I understand that by-ref impls of std::ops are useful, as !Copy types can do math by-ref and avoid a clone. But given an actual signature of &'_ T -> T, what's the advantage of doing this via From rather than Clone?

1 Like

I'm converting between number types in this method; for example taking a reference small number type as input, creating a larger number type out of that without cloning and then doing calculations with it.

Now it is possible to first clone and then convert, but in some cases, this is unnecessarily costly. Which is why you want to use From directly.

The issue of this post arises then when using the more general method with a small integer type for both the small and large type of the previous example.

?? Cost in what metric? Integer copies and conversions are free.

Cost in terms of runtime. Note that it doesn't matter when integers get cloned, but that it does matter for other, larger types. This concerns code written for both small and large types (specialization is unfortunately not an option).

Your suggesting only asks about integers. I'm not entirely sure what you're asking for. Perhaps it would help to provide example code?

1 Like

Take for example a function like this:

fn compute<'a, MaybeLarge1, MaybeLarge2>(left: &mut MaybeLarge1, right: &'a MaybeLarge2)
where
    MaybeLarge1: From<'a MaybeLarge2>,
    ... // A bunch of std::ops, probably
{
    if left.is_zero() {
        *left = From::from(right);
    } else {
        left += right;
    }
    
    ...
}

It is generic over number types, both of which might be large. In case one of them is large, we want to avoid cloning before calling From::from. But it could also be that simply MaybeLarge1 = MaybeLarge2 = i32, in which case the i32: From<'r i32> impl is needed.

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