The opposite of Borrow

If I have a function that needs to borrow a value, but I want to allow the caller to pass either a reference to the value or an owned value, I can of course do this:

fn foo(bar: impl Borrow<Bar>) {
    bar.borrow();
}

But if I'm in the opposite situation where I have a function that needs to take ownership of a value, but I want to allow the caller to pass either a reference (which will be cloned) or an owned value which will be taken as is, I don't know of a general way to do this?

Of course, with types created by me I can implement From and take impl Into<Bar> but I can't do this with external types, whereas Borrow works without an explicit implementation as it has the blanket implementation.

It seems to me that if a type implements Clone then there should be a blanket implementation, either using Into, or some other trait that would make this possible.

As a side question, not meaning to distract from the above, but why does Borrow exist when Into exists? can't there just be a blanket implementation for Into<&T>?

Any reason to not take the value to begin with? Is the clone done conditionally?

Into is more a conversion API, whereas Borrow carries a different semantic. Into is also not object safe, whereas Borrow is.

1 Like

For types like String and PathBuf, impl Into<T> works fine.

That's tricky. Rust doesn't allow overlapping implementations, and doesn't have specialization (yet), so if stdlib provided a blanket implementation, there would be no other way to provide a custom conversion.

In general, I think an interface like this would be surprising, as passing by value would be significantly cheaper for non-trivialize objects than passing by reference would be.

I think the "right" approach is to take an owned value, and let the caller perform the clone if appropriate and necessary.

2 Likes

Maybe std::borrow::ToOwned is what you want.

1 Like

I'm think I'm going to go in this direction. Thank you everyone for your responses.

1 Like