Returning an error/option from Clone::clone

New Rust user here, so forgive me if this is a trivial question.

I noticed that the clone function of the Clone trait returns something of type Self. Trying to change that to Option<Self>, for instance, will fail, with the compiler saying that it's not the type it's expecting.

Having a clone function that can fail seems perfectly natural, though. For instance right now I'm wrapping a C library in Rust, and the C library has a function to duplicate an object. This duplicate function can fail, returning a negative value if it does. If I were to just implement the Clone trait for the corresponding Rust type, the only way I can handle the error is to panic if the return value is not 0.

Alternatively, I could implement a clone function that returns an Error<Self, ...> without implementing the Clone trait. Or I could call this function duplicate to make it clear that it it's not the clone function from the Clone trait...

What is the idiomatic way in Rust to return an error from a clone operation that can fail?

More generally I can see other traits with functions that don't let me return an error. I could want to implement the ToString trait but to_string function returns a String, while internally the C function that will provide me with that string can fail.

For the first one you probably should just write a method try_clone (examples from the std) directly on your struct.

For the second one, you should implement Display not ToString:

ToString shouldn’t be implemented directly: Display should be implemented instead

1 Like

If it fails, it can't be an implementation of Clone. You can either add a separate function/method with whatever signature you like, or introduce a new trait, if such fallible cloning is common for your types.

Look at this from the perspective of a generic function implementation. You expect Clone, but someone sneaks in a fallible impl (assuming it were allowed). How do you deal with it? You can't. You don't expect it, there is nothing you could do but crash, and even that can't be properly expressed in code.

That said, it may be the case that Clone is indeed too restrictive, and ends up changed or deprecated in favour of a different trait. The fallible cloning problem is common if you allow fallible memory allocation in the language. Most clonable but not Copy types own some allocated memory, and would have to reacquire it on clone, which could fail if allocation were fallible. Currently an allocation failure in Rust results either in panic or the process killed by the OS.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.