Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ gh-pages
# git files
.swp
/tags

# RustRover/Other jetbrains IDE files
.idea/
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

### Added
- Add `Clone` and `Copy` derives, similar to `std`'s ones. These derives do not
add any trait bounds on generic parameters by default, making them usable
in more situations. Custom trait bounds can be specified via
`#[clone(bound(...))]` and `#[copy(bound(...))]` attributes.
([#533](https://github.com/JelteF/derive_more/pull/533))
- Add `Default` derive, similar to `std`'s one, but not adding any trait bounds,
the ability to specify custom default values for fields, using non-unit enum
variants as default values and set custom bounds.
([#534](https://github.com/JelteF/derive_more/pull/534))

## 2.1.1 - 2025-12-22

### Fixed
Expand Down
21 changes: 21 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ default = ["std"]
add = ["derive_more-impl/add"]
add_assign = ["derive_more-impl/add_assign"]
as_ref = ["derive_more-impl/as_ref"]
clone = ["derive_more-impl/clone"]
constructor = ["derive_more-impl/constructor"]
copy = ["derive_more-impl/copy"]
debug = ["derive_more-impl/debug"]
default_derive = ["derive_more-impl/default_derive"] # can't use `default` as a feature name as it's reserved
deref = ["derive_more-impl/deref"]
deref_mut = ["derive_more-impl/deref_mut"]
display = ["derive_more-impl/display"]
Expand All @@ -84,8 +87,11 @@ full = [
"add",
"add_assign",
"as_ref",
"clone",
"constructor",
"copy",
"debug",
"default_derive",
"deref",
"deref_mut",
"display",
Expand Down Expand Up @@ -135,16 +141,31 @@ name = "boats_display_derive"
path = "tests/boats_display_derive.rs"
required-features = ["display"]

[[test]]
name = "clone"
path = "tests/clone.rs"
required-features = ["clone"]

[[test]]
name = "constructor"
path = "tests/constructor.rs"
required-features = ["constructor"]

[[test]]
name = "copy"
path = "tests/copy.rs"
required-features = ["copy", "clone"]

[[test]]
name = "debug"
path = "tests/debug.rs"
required-features = ["debug"]

[[test]]
name = "default"
path = "tests/default.rs"
required-features = ["default_derive"]

[[test]]
name = "deref"
path = "tests/deref.rs"
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ These are traits that can be used for operator overloading.
`ShrAssign` and `ShlAssign`
11. [`Eq`], [`PartialEq`]

### Other traits

1. [`Clone`]
2. [`Copy`]
3. [`Default`]


### Static methods

Expand Down Expand Up @@ -264,6 +270,10 @@ Changing [MSRV] (minimum supported Rust version) of this crate is treated as a *
[`Eq`]: https://docs.rs/derive_more/latest/derive_more/derive.Eq.html
[`PartialEq`]: https://docs.rs/derive_more/latest/derive_more/derive.PartialEq.html

[`Clone`]: https://docs.rs/derive_more/latest/derive_more/derive.Clone.html
[`Copy`]: https://docs.rs/derive_more/latest/derive_more/derive.Copy.html
[`Default`]: https://docs.rs/derive_more/latest/derive_more/derive.Default.html

[`Constructor`]: https://docs.rs/derive_more/latest/derive_more/derive.Constructor.html
[`IsVariant`]: https://docs.rs/derive_more/latest/derive_more/derive.IsVariant.html
[`Unwrap`]: https://docs.rs/derive_more/latest/derive_more/derive.Unwrap.html
Expand Down
6 changes: 6 additions & 0 deletions impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ default = []
add = ["syn/extra-traits", "syn/visit"]
add_assign = ["syn/extra-traits", "syn/visit"]
as_ref = ["syn/extra-traits", "syn/visit"]
clone = ["syn/extra-traits"]
constructor = []
copy = ["syn/extra-traits"]
debug = ["syn/extra-traits", "dep:unicode-xid"]
default_derive = ["syn/extra-traits"] # can't use `default` as a feature name as it's reserved
deref = []
deref_mut = []
display = ["syn/extra-traits", "dep:unicode-xid", "dep:convert_case"]
Expand All @@ -79,8 +82,11 @@ full = [
"add",
"add_assign",
"as_ref",
"clone",
"constructor",
"copy",
"debug",
"default_derive",
"deref",
"deref_mut",
"display",
Expand Down
101 changes: 101 additions & 0 deletions impl/doc/clone.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Using `#[derive(Clone)]`

Deriving `Clone` for enums/structs works similarly to the one in `std`,
by cloning all the available fields, but, in contrast:
1. Does not constrain generic parameters.

## Example usage

```rust
use derive_more::{Clone};

#[derive(Clone, Copy, PartialEq, Debug)]
struct Simple(i32);

let a = Simple(42);
let b = a.clone();
assert_eq!(a, b);
```

### Cloning non-`Clone` types references

Because this derive doesn't add any bounds to generic parameters, it can be used with references to non-`Clone` types:

```rust
use derive_more::{Clone};

struct NotClone;

#[derive(Clone)]
struct ReferenceToGenericType<'a, T>(&'a T);

let not_clone = NotClone;
let should_be_clonable = ReferenceToGenericType(&not_clone);
let clone = should_be_clonable.clone();

assert!(core::ptr::eq(should_be_clonable.0, clone.0))
```

this generates code equivalent to:
```rust
# struct NotClone;
# struct ReferenceToGenericType<'a, T>(&'a T);

impl<'a, T> Clone for ReferenceToGenericType<'a, T> {
fn clone(&self) -> Self {
Self(core::clone::Clone::clone(&self.0))
}
}
```

The derive from std would have put a `T: Clone` bound on the clone impl. This is a bit too much as references are
perfectly clonable even if the type behind in not.

### Custom trait bounds

Sometimes you may want to specify custom trait bounds on your generic type parameters.
This can be done with a `#[clone(bound(...))]` attribute.

`#[clone(bound(...))]` accepts code tokens in a format similar to the format used in
angle bracket list (or `where` clause predicates): `T: MyTrait, U: Trait1 + Trait2`.

```rust
use derive_more::Clone;

trait Foo {
type Bar;
}

#[derive(Clone)]
#[clone(bound(T::Bar: Clone))]
struct Baz<T: Foo>(T::Bar);

// FooImpl doesn't implement Clone, but that's fine
// because only T::Bar needs to be Clone
struct FooImpl;

impl Foo for FooImpl {
type Bar = i32;
}

let baz: Baz<FooImpl> = Baz(42);
let cloned = baz.clone();
assert_eq!(baz.0, cloned.0);
```
This generates code equivalent to:
```rust
# trait Foo { type Bar; }
# struct FooImpl;
# impl Foo for FooImpl { type Bar = i32; }
#
# struct Baz<T: Foo>(T::Bar);

impl<T: Foo> Clone for Baz<T>
where
T::Bar: Clone, // specified via `#[clone(bound(...))]`
{
fn clone(&self) -> Self {
Self(core::clone::Clone::clone(&self.0))
}
}
```
102 changes: 102 additions & 0 deletions impl/doc/copy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Using `#[derive(Copy)]`


Deriving ` Copy` for enums/structs works similarly to the one in `std`, but, in contrast:
1. Does not constrain generic parameters.

Note: `Copy` requires `Clone`, so you should derive it as well using [`Clone`].

## Example usage

```rust
use derive_more::{Clone, Copy};

#[derive(Clone, Copy, PartialEq, Debug)]
struct Simple(i32);

let a = Simple(42);
let b = a;
assert_eq!(a, b);
```

### Copying non-`Copy` types references

Because this derive doesn't add any bounds to generic parameters, it can be used with references to non-`Copy` types:

```rust
use derive_more::{Clone, Copy};

struct NotCopy;

#[derive(Clone, Copy)]
struct ReferenceToGenericType<'a, T>(&'a T);

let not_copy = NotCopy;
let should_be_copyable = ReferenceToGenericType(&not_copy);
let copy = should_be_copyable;

assert!(core::ptr::eq(should_be_copyable.0, copy.0))
```

this generates code equivalent to:
```rust
# use derive_more::{Clone};
# struct NotCopy;
# #[derive(Clone)]
# struct ReferenceToGenericType<'a, T>(&'a T);
impl<'a, T> Copy for ReferenceToGenericType<'a, T> { }
```

The derive from std would have put a `T: Copy` bound on the copy impl. This is a bit too much as references are
perfectly copyable even if the type behind in not.

### Custom trait bounds

Sometimes you may want to specify custom trait bounds on your generic type parameters.
This can be done with a `#[copy(bound(...))]` attribute.

`#[copy(bound(...))]` accepts code tokens in a format similar to the format used in
angle bracket list (or `where` clause predicates): `T: MyTrait, U: Trait1 + Trait2`.

```rust
use derive_more::{Clone, Copy};

trait Foo {
type Bar;
}

#[derive(Clone, Copy)]
#[copy(bound(T::Bar: Copy))]
#[clone(bound(T::Bar: Clone))]
struct Baz<T: Foo>(T::Bar);

// FooImpl doesn't implement Clone or Copy, but that's fine
// because only T::Bar needs to be Copy
struct FooImpl;

impl Foo for FooImpl {
type Bar = i32;
}

let baz: Baz<FooImpl> = Baz(42);
let copy = baz;
assert_eq!(baz.0, copy.0);
```

This generates code equivalent to:
```rust
# use derive_more::{Clone};
# trait Foo { type Bar; }
# struct FooImpl;
# impl Foo for FooImpl { type Bar = i32; }
#
# #[derive(Clone)]
# #[clone(bound(T::Bar: Clone))]
# struct Baz<T: Foo>(T::Bar);

impl<T: Foo> Copy for Baz<T>
where
T::Bar: Copy, // specified via `#[copy(bound(...))]`
{
}
```
Loading