Optimization of unused fields in a clone?

Hi,

Suppose I've a struct

struct Foo {
    bar: Bar,
    xyz: Xyz,
}

where Barand Xyz are other potentially large structs.

Suppose I'm trying to do the following:

impl Foo {
    fn example(&self) {
        let Foo { bar, .. } = self.clone();
        // .. Do something that consumes bar
    }
}

What that cause more memory than if I do these instead

impl Foo {
    fn example(&self) {
        let bar = self.bar.clone();
        // .. Do something that consumes bar
    }
}

If there's optimization that only clones the used fields, is such optimization reliably applied in every such usages?

Thanks

Optimization must not change the observable behavior of the code. The <Xyz as Clone>::clone() function may have side effects like interacting with the file system or the stdio. Same applies if the Xyz has a Drop impl with side effect. Eliminating execution of code with side effect change the observable behavior of the code.

2 Likes

Check with rust.godbolt.org (don't forget to add -O to flags)

If clone gets inlined, and the compiler can tell that there are no side effects when cloning (e.g. xyz is just a bunch of integers) then redundant work should be optimized out.

5 Likes

@kornel
It does look like

let Foo { bar, .. } = self.clone();

generates longer and more complex assembly than the other one...

Yeah, HashSet is non-trivial to clone. Heap allocation and running of drop is probably seen as a side effect, so it's not removed.