Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Experiment] [WIP] Add clone_from to clone derive #98445

Conversation

AngelicosPhosphoros
Copy link
Contributor

Fixes #98374

This is still just experiment to run perf, code needs some cleanup.

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 24, 2022
@rust-highfive
Copy link
Collaborator

r? @davidtwco

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 24, 2022
@AngelicosPhosphoros
Copy link
Contributor Author

During last attemp ( #27939 ), there wasn't perf run so we can make more well-founded decision about implementing clone_from now.

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-12 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
........................................................................................ 2728/13103
........................................................................................ 2816/13103
........................................................................................ 2904/13103
....................................i................................................... 2992/13103
...i.......................................................................F.........FFF 3080/13103
F.....................................F................................................. 3168/13103
........................................................................................ 3344/13103
........................................................................................ 3432/13103
........................................................................................ 3520/13103
........................................................................................ 3608/13103
---
...............................................i........i........i.....i................ 11616/13103
..............i......................................................................... 11704/13103
........................................................................................ 11792/13103
........................................................................................ 11880/13103
......................................................F.......F......................... 11968/13103
........................................................................................ 12144/13103
........................................................................................ 12232/13103
.............................i.......................................................... 12320/13103
........................................................................................ 12408/13103
---
To only update this specific test, also pass `--test-args derives/clone-debug-dead-code.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/derives/clone-debug-dead-code.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/clone-debug-dead-code" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/clone-debug-dead-code/auxiliary"
stdout: none
--- stderr -------------------------------
error: field `f` is never read
   |
   |
LL | struct A { f: () }
   |        -   ^^^^^
   |        field in this struct
   |
note: the lint level is defined here
  --> /checkout/src/test/ui/derives/clone-debug-dead-code.rs:4:11
  --> /checkout/src/test/ui/derives/clone-debug-dead-code.rs:4:11
   |
LL | #![forbid(dead_code)]

error: field `f` is never read
  --> /checkout/src/test/ui/derives/clone-debug-dead-code.rs:10:12
   |
   |
LL | struct B { f: () }
   |        -   ^^^^^
   |        field in this struct
   |
   = note: `B` has derived impls for the traits `Clone` and `Clone`, but these are intentionally ignored during dead code analysis


error: field `f` is never read
  --> /checkout/src/test/ui/derives/clone-debug-dead-code.rs:14:12
   |
LL | struct C { f: () }
   |        -   ^^^^^
   |        field in this struct
   |
   = note: `C` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis


error: field `f` is never read
  --> /checkout/src/test/ui/derives/clone-debug-dead-code.rs:18:12
   |
LL | struct D { f: () }
   |        -   ^^^^^
   |        field in this struct
   |
   = note: `D` has derived impls for the traits `Clone` and `Clone` and `Debug`, but these are intentionally ignored during dead code analysis


error: field `f` is never read
  --> /checkout/src/test/ui/derives/clone-debug-dead-code.rs:21:12
   |
LL | struct E { f: () }
   |        -   ^^^^^
   |        field in this struct

error: aborting due to 5 previous errors
------------------------------------------
---
+ LL |      x: Error
+    |      ^^^^^^^^ the trait `Clone` is not implemented for `Error`
+    |
+    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+ help: consider annotating `Error` with `#[derive(Clone)]`
+ LL | #[derive(Clone)]
+    |
+ 
+ error: aborting due to 2 previous errors
---
To only update this specific test, also pass `--test-args derives/derives-span-Clone-enum-struct-variant.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/derives/derives-span-Clone-enum-struct-variant.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/derives-span-Clone-enum-struct-variant" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/derives-span-Clone-enum-struct-variant/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0277]: the trait bound `Error: Clone` is not satisfied
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
...
...
LL |      x: Error //~ ERROR
   |      ^^^^^^^^ the trait `Clone` is not implemented for `Error`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |

error[E0277]: the trait bound `Error: Clone` is not satisfied
error[E0277]: the trait bound `Error: Clone` is not satisfied
  --> /checkout/src/test/ui/derives/derives-span-Clone-enum-struct-variant.rs:9:6
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
...
LL |      x: Error //~ ERROR
   |      ^^^^^^^^ the trait `Clone` is not implemented for `Error`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |

error: aborting due to 2 previous errors
---
+ LL |      Error
+    |      ^^^^^ the trait `Clone` is not implemented for `Error`
+    |
+    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+ help: consider annotating `Error` with `#[derive(Clone)]`
+ LL | #[derive(Clone)]
+    |
+ 
+ error: aborting due to 2 previous errors
---
To only update this specific test, also pass `--test-args derives/derives-span-Clone-enum.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/derives/derives-span-Clone-enum.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/derives-span-Clone-enum" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/derives-span-Clone-enum/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0277]: the trait bound `Error: Clone` is not satisfied
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
...
...
LL |      Error //~ ERROR
   |      ^^^^^ the trait `Clone` is not implemented for `Error`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |

error[E0277]: the trait bound `Error: Clone` is not satisfied
error[E0277]: the trait bound `Error: Clone` is not satisfied
  --> /checkout/src/test/ui/derives/derives-span-Clone-enum.rs:9:6
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
...
LL |      Error //~ ERROR
   |      ^^^^^ the trait `Clone` is not implemented for `Error`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |

error: aborting due to 2 previous errors
---
+ LL |     x: Error
+    |     ^^^^^^^^ the trait `Clone` is not implemented for `Error`
+    |
+    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+ help: consider annotating `Error` with `#[derive(Clone)]`
+ LL | #[derive(Clone)]
+    |
+ 
+ error: aborting due to 2 previous errors
---
To only update this specific test, also pass `--test-args derives/derives-span-Clone-struct.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/derives/derives-span-Clone-struct.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/derives-span-Clone-struct" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/derives-span-Clone-struct/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0277]: the trait bound `Error: Clone` is not satisfied
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
LL | struct Struct {
LL | struct Struct {
LL |     x: Error //~ ERROR
   |     ^^^^^^^^ the trait `Clone` is not implemented for `Error`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |

error[E0277]: the trait bound `Error: Clone` is not satisfied
error[E0277]: the trait bound `Error: Clone` is not satisfied
  --> /checkout/src/test/ui/derives/derives-span-Clone-struct.rs:8:5
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
LL | struct Struct {
LL |     x: Error //~ ERROR
   |     ^^^^^^^^ the trait `Clone` is not implemented for `Error`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |

error: aborting due to 2 previous errors
---
+ LL |     Error
+    |     ^^^^^ the trait `Clone` is not implemented for `Error`
+    |
+    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+ help: consider annotating `Error` with `#[derive(Clone)]`
+ LL | #[derive(Clone)]
+    |
+ 
+ error: aborting due to 2 previous errors
---
To only update this specific test, also pass `--test-args derives/derives-span-Clone-tuple-struct.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/derives/derives-span-Clone-tuple-struct.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/derives-span-Clone-tuple-struct" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/derives-span-Clone-tuple-struct/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0277]: the trait bound `Error: Clone` is not satisfied
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
LL | struct Struct(
LL | struct Struct(
LL |     Error //~ ERROR
   |     ^^^^^ the trait `Clone` is not implemented for `Error`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |

error[E0277]: the trait bound `Error: Clone` is not satisfied
error[E0277]: the trait bound `Error: Clone` is not satisfied
  --> /checkout/src/test/ui/derives/derives-span-Clone-tuple-struct.rs:8:5
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
LL | struct Struct(
LL |     Error //~ ERROR
   |     ^^^^^ the trait `Clone` is not implemented for `Error`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |

error: aborting due to 2 previous errors
---
53 LL | #[derive(Clone)]
54    |
55 
- error: aborting due to 3 previous errors
+ error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied
+    |
+ LL | #[derive(Clone)]
+    |          ----- in this derive macro expansion
+ LL | struct C {
+ LL | struct C {
+ LL |     x: NoCloneOrEq
+    |     ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoCloneOrEq`
+    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+ help: consider annotating `NoCloneOrEq` with `#[derive(Clone)]`
+ LL | #[derive(Clone)]
+    |
+ 
+ error: aborting due to 4 previous errors
---
To only update this specific test, also pass `--test-args derives/deriving-no-inner-impl-error-message.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/derives/deriving-no-inner-impl-error-message.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/deriving-no-inner-impl-error-message" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/derives/deriving-no-inner-impl-error-message/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0369]: binary operation `==` cannot be applied to type `NoCloneOrEq`
   |
   |
LL | #[derive(PartialEq)]
LL | struct E {
LL | struct E {
LL |     x: NoCloneOrEq //~ ERROR binary operation `==` cannot be applied to type `NoCloneOrEq`
   |
   |
note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq`
   |
   |
LL | struct NoCloneOrEq;
   | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>`
   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]`
   |
LL | #[derive(PartialEq)]


error[E0369]: binary operation `!=` cannot be applied to type `NoCloneOrEq`
   |
   |
LL | #[derive(PartialEq)]
LL | struct E {
LL | struct E {
LL |     x: NoCloneOrEq //~ ERROR binary operation `==` cannot be applied to type `NoCloneOrEq`
   |
   |
note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq`
   |
   |
LL | struct NoCloneOrEq;
   | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>`
   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]`
   |
LL | #[derive(PartialEq)]


error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
LL | struct C {
LL | struct C {
LL |     x: NoCloneOrEq
   |     ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoCloneOrEq`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `NoCloneOrEq` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |


error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
LL | struct C {
LL | struct C {
LL |     x: NoCloneOrEq
   |     ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoCloneOrEq`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `NoCloneOrEq` with `#[derive(Clone)]`
LL | #[derive(Clone)]
   |

error: aborting due to 4 previous errors
---
+   --> $DIR/issue-71136.rs:5:5
+    |
+ LL | #[derive(Clone)]
+    |          ----- in this derive macro expansion
+ LL | struct FooHolster {
+ LL |     the_foos: Vec<Foo>,
+    |     ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`
+    = note: required because of the requirements on the impl of `Clone` for `Vec<Foo>`
+    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+ help: consider annotating `Foo` with `#[derive(Clone)]`
+ LL | #[derive(Clone)]
+    |
+ 
+ error: aborting due to 2 previous errors
---
To only update this specific test, also pass `--test-args traits/issue-71136.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/traits/issue-71136.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/traits/issue-71136" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/traits/issue-71136/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0277]: the trait bound `Foo: Clone` is not satisfied
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
   |          ----- in this derive macro expansion
LL | struct FooHolster {
LL |     the_foos: Vec<Foo>, //~ERROR Clone
   |     ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`
   = note: required because of the requirements on the impl of `Clone` for `Vec<Foo>`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Foo` with `#[derive(Clone)]`
   |
---
  --> /checkout/src/test/ui/traits/issue-71136.rs:5:5
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
LL | struct FooHolster {
LL |     the_foos: Vec<Foo>, //~ERROR Clone
   |     ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`
   = note: required because of the requirements on the impl of `Clone` for `Vec<Foo>`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Foo` with `#[derive(Clone)]`
   |
---

---- [ui] src/test/ui/traits/issue-79458.rs stdout ----
diff of stderr:

14    = note: `Clone` is implemented for `&T`, but not for `&mut T`
16 
- error: aborting due to previous error
- error: aborting due to previous error
+ error[E0277]: the trait bound `&'a mut T: Clone` is not satisfied
+    |
+ LL | #[derive(Clone)]
+    |          ----- in this derive macro expansion
+    |          ----- in this derive macro expansion
+ LL | struct Foo<'a, T> {
+ LL |     bar: &'a mut T
+    |     ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&'a mut T`
+    = help: the following other types implement trait `Clone`:
+              &T
+              *const T
+              *mut T
+              *mut T
+    = note: `Clone` is implemented for `&'a T`, but not for `&'a mut T`
+ 
+ error: aborting due to 2 previous errors
18 
19 For more information about this error, try `rustc --explain E0277`.
---
To only update this specific test, also pass `--test-args traits/issue-79458.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/traits/issue-79458.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/traits/issue-79458" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/traits/issue-79458/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0277]: the trait bound `&mut T: Clone` is not satisfied
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
   |          ----- in this derive macro expansion
LL | struct Foo<'a, T> {
LL |     bar: &'a mut T
   |     ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T`
   = help: the following other types implement trait `Clone`:
             &T
             *const T
             *mut T
             *mut T
   = note: `Clone` is implemented for `&T`, but not for `&mut T`


error[E0277]: the trait bound `&'a mut T: Clone` is not satisfied
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
   |          ----- in this derive macro expansion
LL | struct Foo<'a, T> {
LL |     bar: &'a mut T
   |     ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&'a mut T`
   = help: the following other types implement trait `Clone`:
             &T
             *const T
             *mut T
             *mut T
   = note: `Clone` is implemented for `&'a T`, but not for `&'a mut T`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.

@Dylan-DPC
Copy link
Member

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jun 24, 2022
@bors
Copy link
Contributor

bors commented Jun 24, 2022

⌛ Trying commit 861872e with merge f39c353892b43777fbb6a39fd8a2004d9c6b1499...

@nnethercote
Copy link
Contributor

FYI: I'm also in the middle of fiddling with derive code: #98190, #98376, #98446. The first two are r+ and in the queue to merge. It's possible there will be conflicts, hopefully nothing too bad.

#98376 removed the generated ne method for PartialEq, and that was a compile time win. So adding a method to every Clone impl may well hurt compile times, because Clone gets derived a lot.

@AngelicosPhosphoros
Copy link
Contributor Author

AngelicosPhosphoros commented Jun 24, 2022

@nnethercote I think, clone_from can give more performance benefits than specialization of PartialEq::ne because generated code for PartialEq::ne is equivalent to !PartialEq::eq while clone_from can save some allocations in many cases.
I also emit clone_from only for non-Copy types with fields to prevent generating too much code.

Can you explain how you measured compile time wins? I would try to do that too.

@Kobzol
Copy link
Contributor

Kobzol commented Jun 24, 2022

It's already happening :) This PR is currently in the perf. bot queue, once it's done, we will get a comment here with the results of compile time benchmarks.

@scottmcm scottmcm added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. I-libs-api-nominated Nominated for discussion during a libs-api team meeting. labels Jun 24, 2022
@scottmcm
Copy link
Member

scottmcm commented Jun 24, 2022

I'll note that this would change the panic safety of it -- the clone_from that just calls clone is strongly exception safe (baring some perverse interior mutability abuse) whereas if it calls clone_from then panics in the middle could have different results.

So I'll toss this on the @rust-lang/libs-api radar in case they have thoughts about whether it should happen from a semantic perspective (separate from implementation/perf questions).

@AngelicosPhosphoros
Copy link
Contributor Author

@scottmcm

I'll note that this would change the panic safety of it

We already don't exception safe in some important Clone::clone_from implementations (notably, alloc::vec::Vec::clone_from) which can truncate own length and modify first values and got panic in the middle which cause tail part of vec remain same as it was.

So, probably, we should just document in trait definition that clone_from is not panic-safe and user shouldn't use clone_from if exception safety is desired.

@bors
Copy link
Contributor

bors commented Jun 24, 2022

☀️ Try build successful - checks-actions
Build commit: f39c353892b43777fbb6a39fd8a2004d9c6b1499 (f39c353892b43777fbb6a39fd8a2004d9c6b1499)

@rust-timer
Copy link
Collaborator

Queued f39c353892b43777fbb6a39fd8a2004d9c6b1499 with parent fc96600, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (f39c353892b43777fbb6a39fd8a2004d9c6b1499): comparison url.

Instruction count

  • Primary benchmarks: 😿 relevant regressions found
  • Secondary benchmarks: 😿 relevant regressions found
mean1 max count2
Regressions 😿
(primary)
1.3% 4.8% 122
Regressions 😿
(secondary)
20.7% 264.5% 53
Improvements 🎉
(primary)
N/A N/A 0
Improvements 🎉
(secondary)
N/A N/A 0
All 😿🎉 (primary) 1.3% 4.8% 122

Max RSS (memory usage)

Results
  • Primary benchmarks: 😿 relevant regressions found
  • Secondary benchmarks: 😿 relevant regressions found
mean1 max count2
Regressions 😿
(primary)
1.5% 2.6% 15
Regressions 😿
(secondary)
8.0% 11.5% 6
Improvements 🎉
(primary)
N/A N/A 0
Improvements 🎉
(secondary)
-7.0% -7.0% 1
All 😿🎉 (primary) 1.5% 2.6% 15

Cycles

Results
  • Primary benchmarks: 😿 relevant regressions found
  • Secondary benchmarks: 😿 relevant regressions found
mean1 max count2
Regressions 😿
(primary)
2.8% 5.1% 37
Regressions 😿
(secondary)
24.4% 187.9% 33
Improvements 🎉
(primary)
N/A N/A 0
Improvements 🎉
(secondary)
-2.3% -2.3% 1
All 😿🎉 (primary) 2.8% 5.1% 37

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf +perf-regression

Footnotes

  1. the arithmetic mean of the percent change 2 3

  2. number of relevant changes 2 3

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Jun 24, 2022
@AngelicosPhosphoros
Copy link
Contributor Author

Worst case regression (264.5% on issue-58319) is looks like made specifically against clone_from: huge struct with only #[derive(Clone)] on it.
Since this PR doubles amount of code generated in that case, I think, doubling compilation time should be expected here.

@AngelicosPhosphoros
Copy link
Contributor Author

@nnethercote @Kobzol

I think, benchmarking of the compiler doesn't so relevant to average rust program in that case because compiler source already has manually optimized by adding clone_from impls for hot types.
What do you think of such benchmark:

  1. Remove those manual clone_froms.
  2. Run perf on that.
  3. Cherry-pick my changes on top of that.
  4. Run perf again.
  5. Compare perfs on 2 and 4.

IMHO, that would describe expected changes more accurately for average program.

@Kobzol
Copy link
Contributor

Kobzol commented Jun 24, 2022

I'm not really sure what do you mean by that. The perf. suite that was executed checks how long does it take to compile various crates (both artificial stress tests and real-world crates like syn, serde, clap etc.).

So, for example, if this PR was merged, it would take ~1-5% longer to compile crates like regex, diesel, hyper etc. (per the benchmark results). Usually, such compile time regressions are not accepted, unless they fix e.g. some soundness hole or something like that.

Maybe we can do something to optimize the implementation here, but it will probably be quite difficult. We also currently don't have infrastructure for benchmarking compiled programs, to see if the clone_from change has any performance benefits. It would be nice to see some perf. gains from this change from the real world, so that we could assess it's utility.

@oli-obk
Copy link
Contributor

oli-obk commented Jun 24, 2022

So... this is not about clone_from codegen, as that happens regardless of this PR. Maybe we could realize at the point where we codegen the default impl and instead generate a shim that forwards clone_from

@AngelicosPhosphoros
Copy link
Contributor Author

Maybe we could realize at the point where we codegen the default impl and instead generate a shim that forwards clone_from

You mean in the call-site?

I'm not really sure what do you mean by that.

I mean, we would get regression from clone_from (X%) removal and then regression from my changes (Y%). And (X - Y)% would show how other programs would benefit or lose from that.

Maybe it is better just to run some real-world code.

@nnethercote
Copy link
Contributor

FWIW: a 100% result is a 100% increase in compile-time, i.e. a doubling in compilation time. A 264.5% regression is a 3.645x slowdown. It's a weirdly large slowdown.

@oli-obk
Copy link
Contributor

oli-obk commented Jun 24, 2022

You mean in the call-site?

No, I mean the LLVM IR we generate for clone_from could be compiler generated without generating a function in the derive

@AngelicosPhosphoros
Copy link
Contributor Author

AngelicosPhosphoros commented Jun 24, 2022

@nnethercote Thanks for your remark!

I have just run profiling using -Zself-profile on cargo check with master branch and with my changes.

It seems that borrow checker and typechecker really don't like match expression based destructuring.

Diff with base and my changes:

Item Self Time Self Time Change Time Time Change Item count
mir_borrowck +102.1242ms +493.29% +116.7532ms +397.70% +1
typeck +54.7115ms +140.62% +55.7778ms +138.41% +1
metadata_register_crate +11.6217ms +503.21% +23.0361ms +747.17% +0
mir_built +10.1796ms +190.22% +12.6228ms +175.82% +1
check_match +5.4782ms +155.51% +5.5142ms +156.15% +1
hir_lowering +3.6431ms +109.64% +3.6431ms +109.64% +0
expand_crate +3.5499ms +62.59% +15.1705ms +189.01% +0
incr_comp_finalize_session_directory -2.4131ms -61.38% -2.4131ms -61.38% +0
thir_body +2.4057ms +158.66% +2.4075ms +158.61% +1
late_resolve_crate +2.309ms +103.88% +2.309ms +103.88% +0

This values became much better when I manually rewrote Clone impl like

#[inline]
fn clone(&self)->Self{
   Self(::core::clone::Clone::clone(&self.0), ..., ::core::clone::Clone::clone(&self.613),)
}

#[inline]
fn clone(&self, other: &Self){
   ::core::clone::Clone::clone_from(&mut self.0, &other.0);
   ...
   ::core::clone::Clone::clone_from(&mut self.613, &other.613);
}

Results

Item Self Time Self Time Change Time Time Change Item count
typeck +79.3904ms +204.05% +82.0408ms +203.57% +1
mir_borrowck +9.639ms +46.56% +17.071ms +58.15% +1
parse_crate +8.7804ms +943.82% +8.7804ms +943.82% +0
late_resolve_crate +7.8287ms +352.20% +7.8287ms +352.20% +0
mir_built +3.4026ms +63.58% +5.7975ms +80.75% +1
check_match -3.3612ms -95.42% -3.3655ms -95.30% +1
hir_lowering +3.2036ms +96.41% +3.2036ms +96.41% +0
thir_body +2.3983ms +158.17% +2.4003ms +158.13% +1

As you see, difference is nearly 10x on borrow check.

You are removing match statement in #98446 so maybe it is good idea retry perf after you merge that?
May you ping me after merging it?

@conradludgate
Copy link
Contributor

I already started an impl on this 👀 #97528

@m-ou-se
Copy link
Member

m-ou-se commented Jun 27, 2022

Regardless of performancec impact, I'm not sure we can do this, since this changes the clone_from behaviour in a potentially breaking way in the presence of panics, as @scottmcm already mentioned.

@AngelicosPhosphoros
Copy link
Contributor Author

@m-ou-se I made PR with clarification about that guarantees, probably should discuss it there?
#98461

@m-ou-se
Copy link
Member

m-ou-se commented Jun 27, 2022

Since we already have a Vec::clone_from that behaves differently than Vec::clone when stuff panics, it's indeed probably good to update that documentation. But I don't think that means it's fine to silently change the behavior of derived clone_from implementations. People might not depend on Vec::clone_from, but they might depend on TheirOwnType::clone_from.

@m-ou-se m-ou-se removed the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Jul 20, 2022
@joshtriplett
Copy link
Member

We discussed this in today's @rust-lang/libs-api meeting, and we decided not to make this change. People can hand-implement clone_from if they need the performance, but we shouldn't do so by default.

AngelicosPhosphoros added a commit to AngelicosPhosphoros/rust that referenced this pull request Aug 26, 2022
It isn't panic safe de-facto (e.g. for `Vec`) so I just document current behaviour.

Panic safety was mentioned by @scottmcm when discussing [PR with deriving clone_from](rust-lang#98445 (comment)).

Co-authored-by: Jane Losare-Lusby <jlusby42@gmail.com>
@AngelicosPhosphoros AngelicosPhosphoros deleted the add_clone_from_to_clone_derive branch November 22, 2023 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
perf-regression Performance regression. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Derived Clone implementations don't utilize clone_from implementations from field types