Skip to content

Commit b06ca02

Browse files
committed
Sync README
1 parent e869902 commit b06ca02

File tree

2 files changed

+278
-23
lines changed

2 files changed

+278
-23
lines changed

README.md

Lines changed: 258 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,259 @@
1-
# derive-restricted
1+
# derive-where
22

3-
The std derive macros are here:
4-
https://github.com/rust-lang/rust/tree/master/compiler/rustc_builtin_macros/src/deriving
3+
[![Crates.io Version](https://img.shields.io/crates/v/derive-where.svg)](https://crates.io/crates/derive-where)
4+
[![Live Build Status](https://img.shields.io/github/workflow/status/ModProg/derive-where/Test/main)](https://github.com/ModProg/derive-where/actions/workflows/test.yml)
5+
[![Docs.rs Documentation](https://img.shields.io/docsrs/derive-where)](https://docs.rs/crate/derive-where)
6+
7+
## Description
8+
9+
Derive macro to simplify deriving standard and other traits with custom
10+
generic type bounds.
11+
12+
## Usage
13+
14+
```rust
15+
#[derive(DeriveWhere)]
16+
#[derive_where(Clone, Debug)]
17+
struct Example<T>(PhantomData<T>);
18+
```
19+
20+
This will generate trait implementations for `Example` with any `T`,
21+
compared with std's derives, which would only implement these traits with
22+
`T: Trait` bound to the corresponding trait.
23+
24+
In addition, the following convenience options are available:
25+
26+
### Generic type bounds
27+
28+
```rust
29+
#[derive(DeriveWhere)]
30+
#[derive_where(Clone; T)]
31+
struct Example<T, U>(T, PhantomData<U>);
32+
```
33+
34+
Separating the list of trait with a semi-colon, types to bind to can be
35+
specified. This will bind implementation for `Example` to `T: Trait`.
36+
37+
```rust
38+
trait Super: Clone {}
39+
40+
#[derive(DeriveWhere)]
41+
#[derive_where(Clone; T: Super)]
42+
struct Example<T>(PhantomData<T>);
43+
```
44+
45+
This will bind implementation for `Example` to `T: Super`. But more complex
46+
trait bounds are possible:
47+
48+
```rust
49+
trait Trait {
50+
type Type;
51+
}
52+
53+
struct Impl;
54+
55+
impl Trait for Impl {
56+
type Type = i32;
57+
}
58+
59+
#[derive(DeriveWhere)]
60+
#[derive_where(Clone; T::Type)]
61+
struct Example<T: Trait>(T::Type);
62+
```
63+
64+
This will bind implementation for `Example` to `T::Type: Super`. Any
65+
combination of options listed here can be used to satisfy a specific
66+
constrain.
67+
68+
It is also possible to use two separate constrain specification when
69+
required:
70+
71+
```rust
72+
#[derive(DeriveWhere)]
73+
#[derive_where(Clone; T)]
74+
#[derive_where(Debug; U)]
75+
struct Example<T, U>(PhantomData<T>, PhantomData<U>);
76+
```
77+
78+
### Enum default
79+
80+
Deriving [`Default`] on an enum is not possible in Rust at the moment.
81+
Derive-where allows this with a `default` attribute:
82+
83+
```rust
84+
#[derive(DeriveWhere)]
85+
#[derive_where(Default)]
86+
enum Example<T> {
87+
#[derive_where(default)]
88+
A(PhantomData<T>),
89+
}
90+
```
91+
92+
### Skipping fields
93+
94+
With a `skip` or `skip_inner` attribute fields can be skipped for traits
95+
that allow it, which are: [`Debug`], [`Hash`], [`Ord`](https://doc.rust-lang.org/core/cmp/trait.Ord.html), [`PartialOrd`](https://doc.rust-lang.org/core/cmp/trait.PartialOrd.html),
96+
[`PartialEq`](https://doc.rust-lang.org/core/cmp/trait.PartialEq.html) and [`Zeroize`].
97+
98+
```rust
99+
#[derive(DeriveWhere)]
100+
#[derive_where(Debug, PartialEq; T)]
101+
struct Example<T>(#[derive_where(skip)] T);
102+
103+
assert_eq!(format!("{:?}", Example(42)), "Example");
104+
assert_eq!(Example(42), Example(0));
105+
```
106+
107+
It is also possible to skip all fields in an item or variant if desired:
108+
109+
```rust
110+
#[derive(DeriveWhere)]
111+
#[derive_where(Debug)]
112+
#[derive_where(skip_inner)]
113+
struct StructExample<T>(T);
114+
115+
assert_eq!(format!("{:?}", StructExample(42)), "StructExample");
116+
117+
#[derive(DeriveWhere)]
118+
#[derive_where(Debug)]
119+
enum EnumExample<T> {
120+
#[derive_where(skip_inner)]
121+
A(T),
122+
}
123+
124+
assert_eq!(format!("{:?}", EnumExample::A(42)), "A");
125+
```
126+
127+
Selective skipping of fields for certain traits is also an option, both in
128+
`skip` and `skip_inner`:
129+
130+
```rust
131+
#[derive(DeriveWhere)]
132+
#[derive_where(Debug, PartialEq)]
133+
#[derive_where(skip_inner(Debug))]
134+
struct Example<T>(i32, PhantomData<T>);
135+
136+
assert_eq!(format!("{:?}", Example(42, PhantomData::<()>)), "Example");
137+
assert_ne!(
138+
Example(42, PhantomData::<()>),
139+
Example(0, PhantomData::<()>)
140+
);
141+
```
142+
143+
### `Zeroize` options
144+
145+
[`Zeroize`] has three options:
146+
- `crate`: an item-level option which specifies a path to the `zeroize`
147+
crate in case of a re-export or rename.
148+
- `drop`: an item-level option which implements [`Drop`](https://doc.rust-lang.org/core/ops/trait.Drop.html) and uses
149+
[`Zeroize`] to erase all data from memory.
150+
- `fqs`: a field -level option which will use fully-qualified-syntax instead
151+
of calling the [`zeroize`] method on `self` directly. This is to avoid
152+
ambiguity between another method also called `zeroize`.
153+
154+
```rust
155+
#[derive(DeriveWhere)]
156+
#[derive_where(Zeroize(crate = "zeroize_", drop))]
157+
struct Example(#[derive_where(Zeroize(fqs))] i32);
158+
159+
impl Example {
160+
// If we didn't specify the `fqs` option, this would lead to a compile
161+
//error because of method ambiguity.
162+
fn zeroize(&mut self) {
163+
self.0 = 1;
164+
}
165+
}
166+
167+
let mut test = Example(42);
168+
169+
// Will call the struct method.
170+
test.zeroize();
171+
assert_eq!(test.0, 1);
172+
173+
// WIll call the `Zeroize::zeroize` method.
174+
Zeroize::zeroize(&mut test);
175+
assert_eq!(test.0, 0);
176+
```
177+
178+
### Supported traits
179+
180+
The following traits can be derived with derive-where:
181+
- [`Clone`](https://doc.rust-lang.org/core/clone/trait.Clone.html)
182+
- [`Copy`](https://doc.rust-lang.org/core/marker/trait.Copy.html)
183+
- [`Debug`]
184+
- [`Default`]
185+
- [`Eq`](https://doc.rust-lang.org/core/cmp/trait.Eq.html)
186+
- [`Hash`]
187+
- [`Ord`](https://doc.rust-lang.org/core/cmp/trait.Ord.html)
188+
- [`PartialEq`](https://doc.rust-lang.org/core/cmp/trait.PartialEq.html)
189+
- [`PartialOrd`](https://doc.rust-lang.org/core/cmp/trait.PartialOrd.html)
190+
- [`Zeroize`]: Only available with the `zeroize` crate feature.
191+
192+
### Supported items
193+
194+
Structs, tuple structs, unions and enums are supported. Derive-where tries
195+
it's best to discourage usage that could be covered by std's `derive`. For
196+
example unit structs and enums only containing unit variants aren't
197+
supported.
198+
199+
Unions only support [`Clone`](https://doc.rust-lang.org/core/clone/trait.Clone.html) and [`Copy`](https://doc.rust-lang.org/core/marker/trait.Copy.html).
200+
201+
### `no_std` support
202+
203+
`no_std` support is provided by default.
204+
205+
## Crate features
206+
207+
- `nightly`: Implements [`Ord`](https://doc.rust-lang.org/core/cmp/trait.Ord.html) and [`PartialOrd`](https://doc.rust-lang.org/core/cmp/trait.PartialOrd.html) with the help of
208+
[`core::intrinsics::discriminant_value`](https://doc.rust-lang.org/core/intrinsics/fn.discriminant_value.html), which is what Rust does by
209+
default too. Without this feature [`transmute`](https://doc.rust-lang.org/core/mem/fn.transmute.html) is
210+
used to convert [`Discriminant`](https://doc.rust-lang.org/core/mem/struct.Discriminant.html) to a [`i32`](https://doc.rust-lang.org/core/primitive.i32.html),
211+
which is the underlying type.
212+
- `safe`: Implements [`Ord`](https://doc.rust-lang.org/core/cmp/trait.Ord.html) and [`PartialOrd`](https://doc.rust-lang.org/core/cmp/trait.PartialOrd.html) manually. This is much
213+
slower, but might be preferred if you don't trust derive-where. It also
214+
replaces all cases of [`core::hint::unreachable_unchecked`](https://doc.rust-lang.org/core/hint/fn.unreachable_unchecked.html) in [`Ord`](https://doc.rust-lang.org/core/hint/fn.unreachable_unchecked.html),
215+
[`PartialEq`](https://doc.rust-lang.org/core/cmp/trait.PartialEq.html) and [`PartialOrd`](https://doc.rust-lang.org/core/cmp/trait.PartialOrd.html), which is what std uses, with
216+
[`unreachable`](https://doc.rust-lang.org/core/macro.unreachable.html).
217+
- `zeroize`: Allows deriving [`Zeroize`].
218+
219+
## MSRV
220+
221+
The current MSRV is 1.34 and is being checked by the CI. A change will be
222+
accompanied by a minor version bump. If MSRV is important to you, use
223+
`derive-where = "~1.x"` to pin a specific minor version to your crate.
224+
225+
## Alternatives
226+
227+
[derivative](https://crates.io/crates/derivative)
228+
([![Crates.io](https://img.shields.io/crates/v/derivative.svg)](https://crates.io/crates/derivative))
229+
is a great alternative with many options. Notably it has no `no_std`
230+
support.
231+
232+
## Changelog
233+
234+
See the [CHANGELOG] file for details.
235+
236+
## License
237+
238+
Licensed under either of
239+
240+
- Apache License, Version 2.0 ([LICENSE-APACHE] or <http://www.apache.org/licenses/LICENSE-2.0>)
241+
- MIT license ([LICENSE-MIT] or <http://opensource.org/licenses/MIT>)
242+
243+
at your option.
244+
245+
### Contribution
246+
247+
Unless you explicitly state otherwise, any contribution intentionally
248+
submitted for inclusion in the work by you, as defined in the Apache-2.0
249+
license, shall be dual licensed as above, without any additional terms or
250+
conditions.
251+
252+
[CHANGELOG]: https://github.com/getsentry/sentry-native/blob/main/CHANGELOG
253+
[LICENSE-MIT]: https://github.com/getsentry/sentry-native/blob/main/LICENSE-MIT
254+
[LICENSE-APACHE]: https://github.com/getsentry/sentry-native/blob/main/LICENSE-APACHE
255+
[`Debug`]: https://doc.rust-lang.org/core/fmt/trait.Debug.html
256+
[`Default`]: https://doc.rust-lang.org/core/default/trait.Default.html
257+
[`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
258+
[`Zeroize`]: https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html
259+
[`zeroize`]: https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html#tymethod.zeroize

0 commit comments

Comments
 (0)