Obviously whether it does or doesn't will not matter in 99% of cases, but just to help silly anxious developers like me sleep well at night:
Let's say you have code that calls a complex library function that returns a mutable reference, that you then want to return. It also happens that this reference is to a type that implements Clone. So to avoid refactoring too much, you do something like this:
fn common_behavior(specs: Specs) -> ClonableThing {
let mut intermediate_thing = IntermediateThing::new(specs);
let clonable_thing: &mut ClonableThing = intermediate_thing.create_mut_ref_to_thing();
// Will the clone here be reliably optimized out?
std::mem::replace(clonable_thing, clonable_thing.clone())
}
Obviously the replacement value generated by clonable_thing.clone()
will be dropped immediately when intermediate_thing
and everything else goes out of scope, but can we expect that the cloning operation itself will not occur? This is assuming that intermediate_thing
is a fairly complex struct but that the cloning itself is just generated by a #[derive(Clone)]
.
It's not guaranteed by the compiler. In particular, your call to clone()
could have side-effects, in which case the compiler is not allowed to optimize it away.
In practice, if your implementation of clone()
is simple (which is almost always the case), it will generally be optimized away, but the only way to be 100% certain is to disassemble the code.