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
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
21 changes: 4 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -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>);
```
@@ -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>);
```
@@ -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>);
```
@@ -65,7 +61,6 @@ impl Trait for Impl {
type Type = i32;
}

#[derive(DeriveWhere)]
#[derive_where(Clone; T::Type)]
struct Example<T: Trait>(T::Type);
```
@@ -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>);
@@ -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)]
@@ -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);

@@ -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)]
@@ -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>);
@@ -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);

@@ -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);

@@ -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

3 changes: 1 addition & 2 deletions ensure-no-std/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
@@ -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)]
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>);

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>);

Loading