# Optimized Clone of Copy Types?

**URL:** <https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105>\
**Category:** language design\
**Created:** [September 20, 2020, 8:10pm UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105 "2020-09-20T20:10:04Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![jhwgh1968](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhwgh1968/32/7121_2.png) [@jhwgh1968](https://internals.rust-lang.org/u/jhwgh1968)\
**Post date:** [September 20, 2020, 8:10pm UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/1 "2020-09-20T20:10:04Z")

</div>

Hello everyone,

I have a question about the semantics of `Copy` and `Clone`.

Consider this trivial, rather silly program:

```rust
#[derive(Copy, Clone)]
struct Point {
    x: f32,
    y: f32,
}

fn euclidean_distance(p1: &Point, p2: &Point) -> f32 {
    let p1 = p1.clone(); // unnecessary clone
    let p2 = p2.clone(); // unnecessary clone
    ((p2.x - p1.x).powf(2.0) + (p2.y - p1.y).powf(2.0)).sqrt()
}

fn main() {
    let p1 = Point { x: 10.0, y: 1.0 };
    let p2 = Point { x: 1.0, y: 1.0 };

    println!("The distance is {}", euclidean_distance(&p1, &p2));
}

```

Silly though it is, I have similar code repeated over 150 times in a code base, because it is the output of a procedural macro. Here's why.

With the help of a macro, `euclidean_distance` is generated on any type defined by macro inputs. That type may or may not be `Copy`, but it will always be `Clone`.

The generated function always takes references for consistency. (The real function is much more complex, of course, and may not need to make copies.) As a result, when I need owned copies, I must `clone()` them.

Now that I'm starting to use clippy more, I discovered that [it has a lint for that](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone). I was surprised: wouldn't rustc optimize out `Clone` on `Copy` types?

Well, looking at the MIR of the example, the answer is no. The explicit call to clone is still in there, even in release mode. It even uses extra stack slots just to make the call!

Is this a missed optimization, or preserving a language semantic? In other words: does deriving `Copy` _always imply_ that `Clone` is a trivial copy?

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [September 20, 2020, 8:13pm UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/2 "2020-09-20T20:13:36Z")

</div>

This question would probably fit the [users.rust-lang.org](http://users.rust-lang.org) forum way better than this one.

---

<div class="post-metadata">

**Author:** ![jhwgh1968](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhwgh1968/32/7121_2.png) [@jhwgh1968](https://internals.rust-lang.org/u/jhwgh1968)\
**Post date:** [September 20, 2020, 8:15pm UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/3 "2020-09-20T20:15:06Z")

</div>

I thought about that, but none of their categories seemed to fit a rather specific question like this. Do you have a suggestion where I should re-post it?

EDIT: I'll put it in "uncategorized", I guess.

EDIT 2: [cross posted](https://users.rust-lang.org/t/optimizing-clone-of-copy-types/49053). Sorry for the noise!

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [September 20, 2020, 9:01pm UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/4 "2020-09-20T21:01:06Z")

</div>

> [@jhwgh1968](#):
>
> Well, looking at the MIR of the example, the answer is no. The explicit call to clone is still in there, even in release mode. It even uses extra stack slots just to make the call!

I've been contemplating making a mir optimization to fix that, [https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/Rewrite.20.60Call(clone.2C.20\_N).60.20to.20.60Copy(\*\_N).60.3F/near/209852212](https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/Rewrite.20.60Call%28clone.2C.20_N%29.60.20to.20.60Copy%28*_N%29.60.3F/near/209852212)

---

<div class="post-metadata">

**Author:** ![Tom-Phinney](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tom-phinney/32/3299_2.png) [@Tom-Phinney](https://internals.rust-lang.org/u/Tom-Phinney)\
**Post date:** [September 21, 2020, 12:31am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/5 "2020-09-21T00:31:18Z")

</div>

The above macro-generated use case is compelling enough, over the long term and an increasing number of experienced Rust programmers, to justify that optimization.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [September 21, 2020, 2:27am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/6 "2020-09-21T02:27:24Z")

</div>

I’m not sure if I’m personally in favor of such an optimization. I like `Clone` not being magical. I mean, I guess if there are significant performance wins in somewhat realistic scenarios I’d perhaps rethink my opinion here but I’m not fully convinced those exist.

(By “significant” I don’t necessarily mean “large” but just “measurable and in a situation where performance isn’t totally irrelevant”.)

With [specialization](https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md) one could instead offer an alternative to `clone()` which specializes to copying whenever possible, and in a case where you’re unsure about performance implications of `clone` you could call that function/method instead. Also the generated (derived) `Clone` implementation could call that method. ([It currently doesn’t use specialization yet](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1bb0ab465a5fd5ad44d8b913fe6ce903).) Even though that would be a breaking change, too. Maybe a candidate for 2021 edition (or a later one)? _(The idea being: observable changes to what code_ `derive` _generates would be less “breaking” if they only come with a new edition. Although if changing clones to copies in generic code would be considered breaking then libraries doing this would need to go to the next sem-ver version, too.... I’m not sure what to think of this.)_

* * *

I’m also a bit curious if someone could think up (ignoring possibly breaking changes for now) a way to structure the traits `Clone` and `Copy`, possibly with blanket implementations (and perhaps with some new extensions to the trait system), that actually enforces `clone()` to just copy in case the type implements `Copy`. One would need to be able to manually implement `Clone` for a generic type for just the cases where the parameter is `Clone` but not `Copy`.

Would be a bit overkill to think up something like this, if it’s just for `Clone`. But I can imagine different traits in new libraries benefiting from features that are powerful enough to enable these kinds of guarantees. For clone and copy, changing derived instances would do a lot already.

Is there even any types out there (in std of popular crates) that implement `Copy` but have a non-derived `Clone` implementation (for a good reason)?

---

<div class="post-metadata">

**Author:** ![canndrew](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/canndrew/32/1676_2.png) [@canndrew](https://internals.rust-lang.org/u/canndrew)\
**Post date:** [September 21, 2020, 4:44am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/7 "2020-09-21T04:44:07Z")

</div>

> [@steffahn](#):
>
> I’m also a bit curious if someone could think up (ignoring possibly breaking changes for now) a way to structure the traits `Clone` and `Copy` , possibly with blanket implementations (and perhaps with some new extensions to the trait system), that actually enforces `clone()` to just copy in case the type implements `Copy` .

If it was possible to refer to trait methods at the const-generics level then you could have `Copy` require that `Clone::<T>::clone == ptr::read::<T>`:

```rust
trait Copy: Clone<const clone = ptr::read::<Self>> { }

```

This would require that the derived `Clone` impl actually makes `clone` the exact same function as `ptr::read`. Perhaps we could make it so that the type system can "see through" a function in this way if it's marked `#[inline(always)]` and consists of nothing but a call to another function which passes along the arguments in-order. In that case the derived `Clone` impl could look like:

```rust
impl Clone for MyCoolType {
    #[inline(always)]
    fn clone(&self) -> MyCoolType {
        unsafe {
            ptr::read(self)
        }
    }
}

```

There's also the issue that the types don't exactly match (`unsafe` vs non-`unsafe`, `*const T` vs `&T`). But they're close enough that we could allow the type system to still allow you to check for equality.

**Edit:**

> [@canndrew](#):
>
> Perhaps we could make it so that the type system can "see through" a function in this way if it's marked `#[inline(always)]` and consists of nothing but a call to another function which passes along the arguments in-order.

Though, actually, a better way to support this would be to just allow people to declare functions/methods by assigning them a value:

```rust
impl Clone for MyCoolType {
    fn clone = unsafe { ptr::read::<MyCoolType> };
}

```

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [September 21, 2020, 6:11am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/8 "2020-09-21T06:11:36Z")

</div>

> [@jhwgh1968](#):
>
> Well, looking at the MIR of the example, the answer is no

Wait a bit there. Before we all jump on the "missed optimization" bandwagon, let's consider that **CPUs don't execute MIR.** Therefore you shouldn't be looking at the MIR – you should be looking at the generated assembly. It can be quite a bit more optimized than the MIR – after all, the point of the very existence of the MIR is that it's higher-level than assembly or even LLVM IR.

And indeed, it looks like that at `-C opt-level=3`, the code you posted generates _identical_ assembly, whether an explicit `clone()`, an explicit `Copy` (by dereferencing), or none of them (indirect access to the fields) is used:

- [link for original code, explicit `Clone`](https://rust.godbolt.org/z/Wjjvb6)
- [link for `Copy`](https://rust.godbolt.org/z/d7rd75)
- [link for indirect field access](https://rust.godbolt.org/z/hxcj39)

> [@steffahn](#):
>
> I’m not sure if I’m personally in favor of such an optimization. I like `Clone` not being magical.

This. Sure, implementing `Clone` differently for `Copy` types is bad practice, but it would be even worse if the compiler went ahead and just straight up ignored the code of a `Clone` impl completely, for reasons of "optimization".

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [September 21, 2020, 7:31am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/9 "2020-09-21T07:31:21Z")

</div>

> [@steffahn](#):
>
> I like `Clone` not being magical.

> [@H2CO3](#):
>
> but it would be even worse if the compiler went ahead and just straight up ignored the code of a `Clone` impl completely, for reasons of "optimization".

I agree with the general principle here, but `Copy` and `Clone` are so special that there's actually a full RFC from back in May 2016 that this is explicitly allowed: [1521-copy-clone-semantics - The Rust RFC Book](https://rust-lang.github.io/rfcs/1521-copy-clone-semantics.html)

And based on that, `Vec::clone` has been using specialization to `memcpy` once instead of calling `<T as Clone>::clone` N times since Dec 2016. (And, since then, other things like `extend` have been similarly optimized.)

Aside: I've also never seen a place where anyone has actually argued that their side-effectful-`Clone`-but-still-`Copy` was actually a good thing. Do any situations exist where the correct answer to getting impacted by this optimization would be anything but "you should remove `Copy` from the type"?

> [@steffahn](#):
>
> I guess if there are significant performance wins in somewhat realistic scenarios I’d perhaps rethink my opinion here but I’m not fully convinced those exist.

> [@H2CO3](#):
>
> Before we all jump on the "missed optimization" bandwagon, let's consider that **CPUs don't execute MIR.** Therefore you shouldn't be looking at the MIR – you should be looking at the generated assembly. It can be quite a bit more optimized than the MIR – after all, the point of the very existence of the MIR is that it's higher-level than assembly or even LLVM IR.

I certainly expect that it'd be rare, if ever, that this would make a material difference in _runtime_ performance.

However, you know what does execute MIR? Const evaluation in rustc. Where being able to just be an [`Operand::Copy`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.Operand.html) instead of a function call could easily help.

And, more generally, there are plausible _compiler_ performance gains here. The compiler team is already looking at doing MIR-level inlining to improve compile times, and this would be like a really good, really cheap inliner -- saving LLVM from needing to do a bunch of work to inline the implementation and figure out whether it happens to be equivalent to a bitwise copy. And removing the `Call` also means removing the unwind edge, which should mean materially less code to codegen and have LLVM deal with.

Not to mention it'd make other MIR optimizations work better: For example [`dest_prop`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/dest_prop/index.html) can't see through a [`Call`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/terminator/enum.TerminatorKind.html), so this could make it work better. And turning those `Call`s into `Goto`s mean that [`SimplifyCfg`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/simplify/index.html) can collapse all the basic blocks together, so anything working on a single BB will work better.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [September 21, 2020, 7:45am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/10 "2020-09-21T07:45:20Z")

</div>

> [@scottmcm](#):
>
> could easily help

I feel like the burden of proof should not be on me in this case.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [September 21, 2020, 8:33am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/11 "2020-09-21T08:33:40Z")

</div>

([Zulip Archive link for the above discussion](https://zulip-archive.rust-lang.org/189540tcompilerwgmiropt/18175RewriteCallcloneNtoCopyN.html)).

Is there a reason to separate this from the MIR inlining pass? IIRC `derive(Copy, Clone)` is already a special case, so this could just add something like `#[mir_inline(always)]` onto `fn clone` to avoid having to run inlining heuristics.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [September 21, 2020, 11:37am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/12 "2020-09-21T11:37:07Z")

</div>

> [@H2CO3](#):
>
> Wait a bit there. Before we all jump on the "missed optimization" bandwagon, let's consider that **CPUs don't execute MIR.** Therefore you shouldn't be looking at the MIR – you should be looking at the generated assembly. It can be quite a bit more optimized than the MIR – after all, the point of the very existence of the MIR is that it's higher-level than assembly or even LLVM IR.
> 
> And indeed, it looks like that at `-C opt-level=3` , the code you posted generates _identical_ assembly, whether an explicit `clone()` , an explicit `Copy` (by dereferencing), or none of them (indirect access to the fields) is used:

FYI, Pretty much all this has already been said on [URLO](https://users.rust-lang.org/t/optimizing-clone-of-copy-types/49053/3?u=steffahn).

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [September 21, 2020, 4:23pm UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/13 "2020-09-21T16:23:00Z")

</div>

Related, there's a PR to specialize `Clone for Option<T> where T: Copy`:

> <https://github.com/rust-lang/rust/pull/76552>

---

<div class="post-metadata">

**Author:** ![jhwgh1968](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhwgh1968/32/7121_2.png) [@jhwgh1968](https://internals.rust-lang.org/u/jhwgh1968)\
**Post date:** [September 22, 2020, 1:23am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/14 "2020-09-22T01:23:20Z")

</div>

While I generally consider my question answered between these two threads, I feel I should add one last comment: a bit of context about my question.

> [@H2CO3](#):
>
> Wait a bit there. Before we all jump on the "missed optimization" bandwagon, let's consider that **CPUs don't execute MIR.** Therefore you shouldn't be looking at the MIR – you should be looking at the generated assembly.

In general, you are absolutely right. Before I asked, I already confirmed that, for all of the types _currently_ generated by this macro, LLVM optimizes this to a single move (or sometimes, re-use of an input register with zero moves).

That is why the lint struck me -- a lint in the `clippy::perf` group, no less. My question was about _the language_ -- hence my initial choice of the "language design" topic, and IRLO instead of URLO -- with longer-term notions in mind.

All the types I currently use this code on are simple, but it is easy for me to imagine more advanced uses (not yet written) that are more complicated. It makes me ask: will LLVM be as optimal for a `#[repr(C)]` struct with 16 fields, weird alignment, bit packing, and/or a fields bigger than a register?

I also hear, once in a while, about people hoping to use a non-LLVM backend "someday." This also led me to believe that the MIR is the "semantic truth" of the Rust code, and LLVM optimizations are "happy accidents" -- even if they are reliable in practice.

My question was, in effect: what is this lint _actually_ telling me?

I think the answer is: "the language currently does not guarantee any optimizations on your clone call, even though LLVM can probably do them 90% of the time in release mode. If you want it guaranteed, remove it." The MIR seems to reflect that.

The RFC is interesting, and further optimization based on its ramifications are an exciting idea. In effect, it would eliminate the need for that lint. But I defer to the greater expertise in the thread as to whether it would be beneficial.

EDIT: I also tried to reply to @H2CO3, but somehow got @steffahn. Sorry about that.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [September 22, 2020, 5:15am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/15 "2020-09-22T05:15:17Z")

</div>

> [@jhwgh1968](#):
>
> My question was, in effect: what is this lint _actually_ telling me?

Actually, going back to your _given_ example, the lint is definitely correct (for generic types):

```rust
fn euclidean_distance(p1: &Point, p2: &Point) -> f32 {
    let p1 = p1.clone(); // unnecessary clone
    let p2 = p2.clone(); // unnecessary clone
    ((p2.x - p1.x).powf(2.0) + (p2.y - p1.y).powf(2.0)).sqrt()
}

```

The `redundant_clone` lint is telling you that you _don't need to perform the clone at all_, and could just use the borrowed value directly. If your type is _not_ `Copy` and holds some allocation handle, you're needlessly cloning said allocation handle.

The lint it sounds like you're talking about is actually [`clone_on_copy`](https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy), which does explicitly say why it's bad to call `.clone()` on a `Copy` type:

> The only reason `Copy` types implement `Clone` is for generics, not for using the `clone` method on a concrete type.

(Or in other words, make a copy, not a clone, if you know that it is `Copy`. The reason is for clarity, not for performance.)

* * *

For the given example, clippy does in fact emit only `clippy::clone_on_copy` and not `clippy::redundant_clone`.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [September 22, 2020, 1:59pm UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/16 "2020-09-22T13:59:38Z")

</div>

Oh, thanks for spotting this! This answers OPʼs question and my confusion about why Clippy considers `clone()` on copy types a performance problem: _it doesnʼt_.

---

<div class="post-metadata">

**Author:** ![jhwgh1968](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhwgh1968/32/7121_2.png) [@jhwgh1968](https://internals.rust-lang.org/u/jhwgh1968)\
**Post date:** [September 23, 2020, 12:24am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/17 "2020-09-23T00:24:55Z")

</div>

> [@CAD97](#):
>
> The `redundant_clone` lint is telling you that you _don't need to perform the clone at all_ , and could just use the borrowed value directly. If your type is _not_ `Copy` and holds some allocation handle, you're needlessly cloning said allocation handle.

Oh!

I have now removed the `clone()` causing the lint, and you're absolutely right. The behavior is unchanged.

Thank you!

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [December 22, 2020, 12:24am UTC](https://internals.rust-lang.org/t/optimized-clone-of-copy-types/13105/18 "2020-12-22T00:24:56Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
