Question about implicit deref coercion for methods

Hi all,

I'm justing watching the Crust of Rust video series from Jon Gjengst - awesome education material in my opinion.

But in the video about channels he says here that you have to call explicitly clone on Arc with Arc::clone(&self.shared) instead of self.shared.clone() so that deref doesn't recurse and unintentionally clones the inner type. I cannot reproduce this behaviour and the docs say about this case:

It happens automatically when we pass a reference to a particular type’s value as an argument to a function or method that doesn’t match the parameter type in the function or method definition.

Which isn't the case for Arc so no recursive/greedy deref behaviour here.

Am I misunderstanding something or might he be mistaken in his video?

Regards keks

It's just an extra piece of caution, unnecessary IMO. Since Arc is Clone, an_arc.clone() does unambiguously refer to <Arc as Clone>::clone(). I don't know how you can make it accidentally refer to the inner type's clone method, but despite being warned against it perpetually, this kind of error simply never occurred to me.

5 Likes

There's a relatively common misconception that .clone() is not idiomatic, because using Arc::clone was the strongly suggested way for a couple years. But it was formally decided that's not really the case (in practice .clone() is widely used, including in the rustc and std code bases) and it stopped being strongly suggested in most official documentation.

There's another relatively common misconception that the strong recommendations were because of ambiguity due to Arc's Deref implementation, but that's also not the case. It was strongly recommended in order to emphasize a cheap, shallow clone is taking place, and not an expensive, deep(er) clone.

Here's a comment from when I looked up the history (with links).

6 Likes

When I learnt Rust, I was told to use Arc::clone(&self.shared), Rc::clone(&self.shared) etc instead of self.shared.clone() so that if someone refactored to remove the refcounting wrapper, they'd be pointed at all the places where I'd assumed that a clone was just a refcount increment by the resulting stack of compiler errors.

My experience since then has been that that sort of refactor is rare, and that when people do them, they'll look at performance numbers anyway, so it doesn't matter. Either my clone is on a rare codepath, and it doesn't affect performance, or they'll ensure that clone() is still cheap after the refactor.

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.