Skip to content

derive_where attribute macro instead of derive macro #33

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

Merged
merged 12 commits into from
Jan 10, 2022
Merged
21 changes: 4 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ generic type bounds.
## Usage

The `derive_where` macro can be used just like std's `#[derive(...)]`
statements, with the only caveat that it requires to derive `DeriveWhere`
([#27]):
statements:

```rust
#[derive(DeriveWhere)]
#[derive_where(Clone, Debug)]
struct Example<T>(PhantomData<T>);
```
Expand All @@ -34,7 +32,6 @@ specified. This example will restrict the implementation for `Example` to
`T: Clone`:

```rust
#[derive(DeriveWhere)]
#[derive_where(Clone; T)]
struct Example<T, U>(T, PhantomData<U>);
```
Expand All @@ -45,7 +42,6 @@ bind implementation for `Example` to `T: Super`:
```rust
trait Super: Clone {}

#[derive(DeriveWhere)]
#[derive_where(Clone; T: Super)]
struct Example<T>(PhantomData<T>);
```
Expand All @@ -65,7 +61,6 @@ impl Trait for Impl {
type Type = i32;
}

#[derive(DeriveWhere)]
#[derive_where(Clone; T::Type)]
struct Example<T: Trait>(T::Type);
```
Expand All @@ -75,7 +70,6 @@ specific constrain. It is also possible to use multiple separate
constrain specifications when required:

```rust
#[derive(DeriveWhere)]
#[derive_where(Clone; T)]
#[derive_where(Debug; U)]
struct Example<T, U>(PhantomData<T>, PhantomData<U>);
Expand All @@ -87,7 +81,6 @@ Deriving [`Default`] on an enum is not possible in Rust at the moment.
Derive-where allows this with a `default` attribute:

```rust
#[derive(DeriveWhere)]
#[derive_where(Default)]
enum Example<T> {
#[derive_where(default)]
Expand All @@ -102,7 +95,6 @@ that allow it, which are: [`Debug`], [`Hash`], [`Ord`](https://doc.rust-lang.org
[`PartialEq`](https://doc.rust-lang.org/core/cmp/trait.PartialEq.html), [`Zeroize`] and [`ZeroizeOnDrop`].

```rust
#[derive(DeriveWhere)]
#[derive_where(Debug, PartialEq; T)]
struct Example<T>(#[derive_where(skip)] T);

Expand All @@ -113,14 +105,12 @@ assert_eq!(Example(42), Example(0));
It is also possible to skip all fields in an item or variant if desired:

```rust
#[derive(DeriveWhere)]
#[derive_where(Debug)]
#[derive_where(skip_inner)]
struct StructExample<T>(T);

assert_eq!(format!("{:?}", StructExample(42)), "StructExample");

#[derive(DeriveWhere)]
#[derive_where(Debug)]
enum EnumExample<T> {
#[derive_where(skip_inner)]
Expand All @@ -134,7 +124,6 @@ Selective skipping of fields for certain traits is also an option, both in
`skip` and `skip_inner`:

```rust
#[derive(DeriveWhere)]
#[derive_where(Debug, PartialEq)]
#[derive_where(skip_inner(Debug))]
struct Example<T>(i32, PhantomData<T>);
Expand All @@ -156,7 +145,6 @@ assert_ne!(
This is to avoid ambiguity between another method also called `zeroize`.

```rust
#[derive(DeriveWhere)]
#[derive_where(Zeroize(crate = "zeroize_"))]
struct Example(#[derive_where(Zeroize(fqs))] i32);

Expand Down Expand Up @@ -189,8 +177,7 @@ and can be implemented without [`Zeroize`], otherwise it only implements
- `crate`: an item-level option which specifies a path to the `zeroize`
crate in case of a re-export or rename.

```
#[derive(DeriveWhere)]
```rust
#[derive_where(ZeroizeOnDrop(crate = "zeroize_"))]
struct Example(i32);

Expand Down Expand Up @@ -253,8 +240,8 @@ accompanied by a minor version bump. If MSRV is important to you, use

[derivative](https://crates.io/crates/derivative)
([![Crates.io](https://img.shields.io/crates/v/derivative.svg)](https://crates.io/crates/derivative))
is a great alternative with many options. Notably it has no `no_std`
support.
is a great alternative with many options. Notably it doesn't support `no_std`
and requires an extra `#[derive(Derivative)]` to use.

## Changelog

Expand Down
3 changes: 1 addition & 2 deletions ensure-no-std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ extern crate zeroize_ as zeroize;

use core::marker::PhantomData;

use derive_where::DeriveWhere;
use derive_where::derive_where;

#[derive(DeriveWhere)]
#[derive_where(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "zeroize", derive_where(Zeroize))]
pub struct Test<T>(PhantomData<T>);
8 changes: 1 addition & 7 deletions non-msrv-tests/tests/ui/default.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
use std::marker::PhantomData;

use derive_where::DeriveWhere;
use derive_where::derive_where;

#[derive(DeriveWhere)]
#[derive_where(Debug)]
struct DefaultOnStruct<T>(#[derive_where(default)] PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Clone)]
enum DefaultWithoutTrait<T> {
#[derive_where(default)]
A(PhantomData<T>),
}

#[derive(DeriveWhere)]
#[derive_where(Default)]
enum MissingDefault<T> {
A(PhantomData<T>),
}

#[derive(DeriveWhere)]
#[derive_where(Default)]
enum DuplicateDefaultSeparate<T> {
#[derive_where(default)]
Expand All @@ -28,14 +24,12 @@ enum DuplicateDefaultSeparate<T> {
B(PhantomData<T>),
}

#[derive(DeriveWhere)]
#[derive_where(Default)]
enum DuplicateDefaultSame<T> {
#[derive_where(default, default)]
A(PhantomData<T>),
}

#[derive(DeriveWhere)]
#[derive_where(Default)]
enum DuplicateDefaultSameSeparate<T> {
#[derive_where(default)]
Expand Down
29 changes: 14 additions & 15 deletions non-msrv-tests/tests/ui/default.stderr
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
error: unknown option
--> tests/ui/default.rs:7:42
--> tests/ui/default.rs:6:42
|
7 | struct DefaultOnStruct<T>(#[derive_where(default)] PhantomData<T>);
6 | struct DefaultOnStruct<T>(#[derive_where(default)] PhantomData<T>);
| ^^^^^^^

error: `default` is only supported if `Default` is being implemented
--> tests/ui/default.rs:12:17
--> tests/ui/default.rs:10:17
|
12 | #[derive_where(default)]
10 | #[derive_where(default)]
| ^^^^^^^

error: required `default` option on a variant if `Default` is being implemented
--> tests/ui/default.rs:17:1
--> tests/ui/default.rs:15:1
|
17 | / #[derive_where(Default)]
18 | | enum MissingDefault<T> {
19 | | A(PhantomData<T>),
20 | | }
15 | / enum MissingDefault<T> {
16 | | A(PhantomData<T>),
17 | | }
| |_^

error: multiple `default` options in enum
--> tests/ui/default.rs:27:17
--> tests/ui/default.rs:23:17
|
27 | #[derive_where(default)]
23 | #[derive_where(default)]
| ^^^^^^^

error: duplicate `default` option
--> tests/ui/default.rs:34:26
--> tests/ui/default.rs:29:26
|
34 | #[derive_where(default, default)]
29 | #[derive_where(default, default)]
| ^^^^^^^

error: duplicate `default` option
--> tests/ui/default.rs:42:17
--> tests/ui/default.rs:36:17
|
42 | #[derive_where(default)]
36 | #[derive_where(default)]
| ^^^^^^^
13 changes: 1 addition & 12 deletions non-msrv-tests/tests/ui/item.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,28 @@
use std::marker::PhantomData;

use derive_where::DeriveWhere;
use derive_where::derive_where;

#[derive(DeriveWhere)]
struct NoAttribute<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where]
struct NoOption<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where()]
struct EmptyAttribute<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Clone; T;)]
struct SemiColonAtTheEnd<T, U>(T, PhantomData<U>);

#[derive(DeriveWhere)]
#[derive_where(Clone; T,,)]
struct DoubleColonAtTheEnd<T, U>(T, PhantomData<U>);

#[derive(derive_where::DeriveWhere)]
#[derive_where(Clone; where)]
struct InvalidGeneric<T>(PhantomData<T>);

#[derive(derive_where::DeriveWhere)]
#[derive_where(Clone Debug)]
struct MissingCommaBetweenTraits<T>(PhantomData<T>);

#[derive(derive_where::DeriveWhere)]
#[derive_where(Clone; T U)]
struct MissingCommaBetweenGenerics<T, U, V>(T, PhantomData<(U, V)>);

#[derive(DeriveWhere)]
#[derive_where("Clone")]
struct InvalidTrait<T>(PhantomData<T>);

Expand Down
48 changes: 23 additions & 25 deletions non-msrv-tests/tests/ui/item.stderr
Original file line number Diff line number Diff line change
@@ -1,53 +1,51 @@
error: no traits found to implement, use `#[derive_where(..)` to specify some
--> tests/ui/item.rs:6:1
error: empty `derive_where` found
--> tests/ui/item.rs:5:1
|
6 | struct NoAttribute<T>(PhantomData<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: unexpected option syntax
--> tests/ui/item.rs:9:3
5 | #[derive_where]
| ^^^^^^^^^^^^^^^
|
9 | #[derive_where]
| ^^^^^^^^^^^^
= note: this error originates in the attribute macro `derive_where` (in Nightly builds, run with -Z macro-backtrace for more info)

error: empty `derive_where` found
--> tests/ui/item.rs:13:3
|
13 | #[derive_where()]
| ^^^^^^^^^^^^^^
--> tests/ui/item.rs:8:1
|
8 | #[derive_where()]
| ^^^^^^^^^^^^^^^^^
|
= note: this error originates in the attribute macro `derive_where` (in Nightly builds, run with -Z macro-backtrace for more info)

error: expected `,`
--> tests/ui/item.rs:17:24
--> tests/ui/item.rs:11:24
|
17 | #[derive_where(Clone; T;)]
11 | #[derive_where(Clone; T;)]
| ^

error: expected type to bind to, expected one of: `for`, parentheses, `fn`, `unsafe`, `extern`, identifier, `::`, `<`, square brackets, `*`, `&`, `!`, `impl`, `_`, lifetime
--> tests/ui/item.rs:21:25
--> tests/ui/item.rs:14:25
|
21 | #[derive_where(Clone; T,,)]
14 | #[derive_where(Clone; T,,)]
| ^

error: expected type to bind to, expected one of: `for`, parentheses, `fn`, `unsafe`, `extern`, identifier, `::`, `<`, square brackets, `*`, `&`, `!`, `impl`, `_`, lifetime
--> tests/ui/item.rs:25:23
--> tests/ui/item.rs:17:23
|
25 | #[derive_where(Clone; where)]
17 | #[derive_where(Clone; where)]
| ^^^^^

error: expected `;` or `,
--> tests/ui/item.rs:29:22
--> tests/ui/item.rs:20:22
|
29 | #[derive_where(Clone Debug)]
20 | #[derive_where(Clone Debug)]
| ^^^^^

error: expected `,`
--> tests/ui/item.rs:33:25
--> tests/ui/item.rs:23:25
|
33 | #[derive_where(Clone; T U)]
23 | #[derive_where(Clone; T U)]
| ^

error: unexpected option syntax
--> tests/ui/item.rs:37:16
--> tests/ui/item.rs:26:16
|
37 | #[derive_where("Clone")]
26 | #[derive_where("Clone")]
| ^^^^^^^
12 changes: 1 addition & 11 deletions non-msrv-tests/tests/ui/item_option_syntax.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,19 @@
use std::marker::PhantomData;

use derive_where::DeriveWhere;
use derive_where::derive_where;

#[derive(DeriveWhere)]
// Rust itself already fails to parse this and will provide a separate error message.
#[derive_where = invalid]
struct InvalidAttribute<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where = "invalid"]
struct WrongAttributeSyntax<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where()]
struct EmptyAttribute<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Debug = "option")]
struct WrongOptionSyntax<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Debug())]
struct EmptyOption<T>(PhantomData<T>);

#[derive(derive_where::DeriveWhere)]
#[derive_where(Debug(option))]
struct UnsupportedOption<T>(PhantomData<T>);

Expand Down
Loading