summaryrefslogtreecommitdiffstats
path: root/vendor/derivative/doc/cmp.md
blob: b6ff4903ee04d0dce74ed99d400fc56eb6817eba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Custom attributes
The `PartialEq`, `Eq`, `PartialOrd` and `Eq` and traits support the following attributes:

* **Container attributes**
    * [`<CmpTrait>(bound="<where-clause or empty>")`](#custom-bound)
* **Field attributes**
    * [`<CmpTrait>(bound="<where-clause or empty>")`](#custom-bound)

The `PartialEq`, `PartialOrd` and `Ord` traits also supports the following attributes:

* **Container attributes**
    * [`<CmpTrait>="feature_allow_slow_enum"`](#enumerations)
* **Field attributes**
    * [`<CmpTrait>="ignore"`](#ignoring-a-field)
    * [`<CmpTrait>(compare_with="<path>")`](#compare-with)

(These attributes are not relevant for `Eq` which is just a marker trait.)

# Enumerations

Unfortunately, there is no way for derivative to derive `PartialOrd` or `Ord` on
enumerations as efficiently as the built-in `derive(…)` yet.

If you want to use derivative on enumerations anyway, you can add

```rust,ignore
#[derivative(PartialOrd="feature_allow_slow_enum")]
```

to your enumeration. This acts as a “feature-gate”.

This attribute is also allowed for `PartialEq` for historical reason. It is not
necessary anymore as of v2.1.0. It was never necessary nor allowed for `Eq`.

# Ignoring a field

You can use *derivative* to ignore a field when comparing:

```rust
# extern crate derivative;
# use derivative::Derivative;
#[derive(Derivative)]
#[derivative(PartialEq)]
struct Foo {
    foo: u8,
    #[derivative(PartialEq="ignore")]
    bar: u8,
}

assert!(Foo { foo: 0, bar: 42 } == Foo { foo: 0, bar: 7});
assert!(Foo { foo: 42, bar: 0 } != Foo { foo: 7, bar: 0});
```

# Compare with

Usually fields are compared using `==`, `PartialOrd::partial_cmp` or `Ord::cmp`. You can use an alternative comparison
function if you like:

```rust
# extern crate derivative;
# use derivative::Derivative;
# mod path {
#   pub struct SomeTypeThatMightNotBePartialEq;
#   pub mod to {
#     pub fn my_cmp_fn(_: &super::SomeTypeThatMightNotBePartialEq, _: &super::SomeTypeThatMightNotBePartialEq) -> bool { false }
#   }
# }
# use path::SomeTypeThatMightNotBePartialEq;
#[derive(Derivative)]
#[derivative(PartialEq)]
struct Foo {
    foo: u32,
    #[derivative(PartialEq(compare_with="path::to::my_cmp_fn"))]
    bar: SomeTypeThatMightNotBePartialEq,
}
```

`foo` will be compared with `==` and `bar` will be compared with
`path::to::my_cmp_fn` which must have the following prototype:

| Trait        | Signature |
|--------------|-----------|
| `PartialEq`  | <span class="rust">`fn my_cmp_fn(&T, &T) -> bool;`</span>
| `PartialOrd` | <span class="rust">`fn my_cmp_fn(&T, &T) -> std::option::Option<std::cmp::Ordering>;`</span>
| `Ord`        | <span class="rust">`fn my_cmp_fn(&T, &T) -> std::cmp::Ordering;`</span>

# Custom bound

Usually if you derive `CmpTrait`, a `T: CmpTrait` bound is added for each type parameter `T`. You can use
override this behavior if the inferred bound is not correct for you.

Eg. comparing raw pointers does not require the type to be `Eq`, so you could
use:

```rust
# extern crate derivative;
# use derivative::Derivative;
#[derive(Derivative)]
#[derivative(PartialEq)]
struct WithPtr<T: ?Sized> {
    #[derivative(PartialEq(bound=""))]
    foo: *const T
}
```

See [`Default`'s documentation](./Default.md#custom-bound) for more details.

# Packed structures

You can use *derivative* to implement the comparison traits on packed structures. Unlike the standard `derive`, *derivative* does not require the structure itself to be `Copy`, but like the standard `derive`, it requires each (non-ignored) field to be `Copy`.

```rust
# extern crate derivative;
# use derivative::Derivative;
#[derive(Derivative)]
#[derivative(PartialEq)]
#[repr(C, packed)]
struct Foo {
    f: u32,
    #[derivative(PartialEq = "ignore")]
    t: String,
}
```