rust-lang / rust-lang/rust

Derived `Clone` impl is not simplified if `Clone` is derived before `Copy`

Open
#124,794 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

A-macros C-bug C-optimization T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Of these 4 ways to derive Copy and Clone:

#[derive(Copy, Clone)]
struct Foo(i32);

#[derive(Clone, Copy)]
struct Bar(i32);

#[derive(Copy)]
#[derive(Clone)]
struct Baz(i32);

#[derive(Clone)]
#[derive(Copy)]
struct Qux(i32);

The last one (derive Clone, then derive Copy) does not use the simplified form of the Clone derive for Copy types:

struct Foo(i32);
#[automatically_derived]
impl ::core::marker::Copy for Foo { }
#[automatically_derived]
impl ::core::clone::Clone for Foo {
    #[inline]
    fn clone(&self) -> Foo {
        let _: ::core::clone::AssertParamIsClone<i32>;
        *self
    }
}

struct Bar(i32);
#[automatically_derived]
impl ::core::clone::Clone for Bar {
    #[inline]
    fn clone(&self) -> Bar {
        let _: ::core::clone::AssertParamIsClone<i32>;
        *self
    }
}
#[automatically_derived]
impl ::core::marker::Copy for Bar { }

struct Baz(i32);
#[automatically_derived]
impl ::core::clone::Clone for Baz {
    #[inline]
    fn clone(&self) -> Baz {
        let _: ::core::clone::AssertParamIsClone<i32>;
        *self
    }
}
#[automatically_derived]
impl ::core::marker::Copy for Baz { }

struct Qux(i32);
#[automatically_derived]
impl ::core::marker::Copy for Qux { }
#[automatically_derived]
impl ::core::clone::Clone for Qux {
    #[inline]
    fn clone(&self) -> Qux { Qux(::core::clone::Clone::clone(&self.0)) }
}

I don't think this leads to any problems currently, but it's an odd (kind of amusing) inconsistency and may (citation needed) make for slightly worse codegen.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the four derive-order examples and comparing their generated Clone implementations. Trace the Rust compiler's derive handling for Clone and Copy to find why the final ordering is treated differently. Done means the last example uses the same simplified Clone implementation without changing the behavior of the other three cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.