diff --git a/CHANGELOG.md b/CHANGELOG.md index 87ac7e6..8691956 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added +- Allow skipping fields for `Clone`, calling `Default::default()` instead. + **Note:** `Clone` is excluded from blanket skipping and can only be used with + selective skipping to avoid this being a breaking change. + ## [1.3.0] - 2025-04-21 ### Added diff --git a/README.md b/README.md index af1d1bf..9c52214 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,7 @@ Selective skipping of fields for certain traits is also an option, both in `skip` and `skip_inner`. To prevent breaking invariants defined for these traits, some of them can only be skipped in groups. The following groups are available: +- [`Clone`]: Uses [`Default`] instead of [`Clone`]. - [`Debug`] - `EqHashOrd`: Skips [`Eq`], [`Hash`], [`Ord`], [`PartialOrd`] and [`PartialEq`]. diff --git a/src/attr/item.rs b/src/attr/item.rs index c021be0..215b23a 100644 --- a/src/attr/item.rs +++ b/src/attr/item.rs @@ -259,7 +259,7 @@ impl DeriveWhere { pub fn any_skip(&self) -> bool { self.traits .iter() - .any(|trait_| SkipGroup::trait_supported(**trait_)) + .any(|trait_| SkipGroup::trait_supported_by_skip_all(**trait_)) } /// Create [`WhereClause`] for the given parameters. diff --git a/src/attr/skip.rs b/src/attr/skip.rs index cd8fc9e..1a56168 100644 --- a/src/attr/skip.rs +++ b/src/attr/skip.rs @@ -4,7 +4,7 @@ use std::default::Default; use syn::{spanned::Spanned, Meta, Path, Result}; -use crate::{util::MetaListExt, DeriveWhere, Error, Trait}; +use crate::{attr::DeriveTrait, util::MetaListExt, DeriveWhere, Error, Trait}; /// Stores what [`Trait`]s to skip this field or variant for. #[cfg_attr(test, derive(Debug))] @@ -101,6 +101,18 @@ impl Skip { if let Meta::Path(path) = nested_meta { let skip_group = SkipGroup::from_path(path)?; + if skip_group == SkipGroup::Clone + && derive_wheres.iter().any(|derive_where| { + derive_where + .traits + .iter() + .any(|trait_| trait_ == &DeriveTrait::Copy) + }) { + return Err(Error::unable_to_skip_clone_while_deriving_copy( + path.span(), + )); + } + // Don't allow to skip the same trait twice. if traits.contains(&skip_group) { return Err(Error::option_skip_duplicate( @@ -144,7 +156,7 @@ impl Skip { pub fn trait_skipped(&self, trait_: Trait) -> bool { match self { Skip::None => false, - Skip::All => SkipGroup::trait_supported(trait_), + Skip::All => SkipGroup::trait_supported_by_skip_all(trait_), Skip::Traits(skip_groups) => skip_groups .iter() .any(|skip_group| skip_group.traits().any(|this_trait| this_trait == trait_)), @@ -166,6 +178,8 @@ impl Skip { #[derive(Clone, Copy, Eq, PartialEq)] #[cfg_attr(test, derive(Debug))] pub enum SkipGroup { + /// [`Clone`]. + Clone, /// [`Debug`]. Debug, /// [`Eq`], [`Hash`], [`Ord`], [`PartialEq`] and [`PartialOrd`]. @@ -185,6 +199,7 @@ impl SkipGroup { use SkipGroup::*; match ident.to_string().as_str() { + "Clone" => Ok(Clone), "Debug" => Ok(Debug), "EqHashOrd" => Ok(EqHashOrd), "Hash" => Ok(Hash), @@ -202,6 +217,7 @@ impl SkipGroup { /// messages. const fn as_str(self) -> &'static str { match self { + Self::Clone => "Clone", Self::Debug => "Debug", Self::EqHashOrd => "EqHashOrd", Self::Hash => "Hash", @@ -213,6 +229,9 @@ impl SkipGroup { /// [`Trait`]s supported by this group. fn traits(self) -> impl Iterator { match self { + Self::Clone => [Some(Trait::Clone), None, None, None, None] + .into_iter() + .flatten(), Self::Debug => [Some(Trait::Debug), None, None, None, None] .into_iter() .flatten(), @@ -242,7 +261,7 @@ impl SkipGroup { } /// Returns `true` if [`Trait`] is supported by any group. - pub fn trait_supported(trait_: Trait) -> bool { + pub fn trait_supported_by_skip_all(trait_: Trait) -> bool { match trait_ { Trait::Clone | Trait::Copy | Trait::Default => false, Trait::Debug diff --git a/src/data.rs b/src/data.rs index e2f3553..4b54e18 100644 --- a/src/data.rs +++ b/src/data.rs @@ -311,7 +311,7 @@ impl<'a> Data<'a> { } /// Returns `true` if all fields are skipped with that [`Trait`]. - fn skip(&self, trait_: Trait) -> bool { + pub fn skip(&self, trait_: Trait) -> bool { self.skip_inner.trait_skipped(trait_) || match self.fields() { Either::Left(fields) => fields.skip(trait_), diff --git a/src/error.rs b/src/error.rs index 9557ac5..1b93e40 100644 --- a/src/error.rs +++ b/src/error.rs @@ -277,6 +277,11 @@ impl Error { ) } + /// Unsupported `skip(Clone)` while deriving copy. + pub fn unable_to_skip_clone_while_deriving_copy(skip_clone: Span) -> syn::Error { + syn::Error::new(skip_clone, "Cannot skip `Clone` while deriving `Copy`") + } + /// List of available [`Trait`](crate::Trait)s. fn trait_list() -> String { [ @@ -300,6 +305,7 @@ impl Error { /// List of available [`SkipGroup`](crate::SkipGroup)s. fn skip_group_list() -> String { [ + "Clone", "Debug", "EqHashOrd", "Hash", diff --git a/src/lib.rs b/src/lib.rs index 5db30e3..c5df73e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -170,6 +170,7 @@ //! `skip` and `skip_inner`. To prevent breaking invariants defined for these //! traits, some of them can only be skipped in groups. The following groups are //! available: +//! - [`Clone`]: Uses [`Default`] instead of [`Clone`]. //! - [`Debug`] //! - `EqHashOrd`: Skips [`Eq`], [`Hash`], [`Ord`], [`PartialOrd`] and //! [`PartialEq`]. diff --git a/src/test/bound.rs b/src/test/bound.rs index a84d0c2..a26658c 100644 --- a/src/test/bound.rs +++ b/src/test/bound.rs @@ -18,7 +18,7 @@ fn bound() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0, ref __field_1) => Test(::core::clone::Clone::clone(__field_0), ::core::clone::Clone::clone(__field_1)), + Test(ref __field_0, ref __field_1) => Test { 0: ::core::clone::Clone::clone(__field_0), 1: ::core::clone::Clone::clone(__field_1) }, } } } @@ -48,7 +48,7 @@ fn bound_multiple() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0, ref __field_1) => Test(::core::clone::Clone::clone(__field_0), ::core::clone::Clone::clone(__field_1)), + Test(ref __field_0, ref __field_1) => Test{ 0: ::core::clone::Clone::clone(__field_0), 1: ::core::clone::Clone::clone(__field_1) }, } } } @@ -78,7 +78,7 @@ fn custom_bound() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0) => Test(::core::clone::Clone::clone(__field_0)), + Test(ref __field_0) => Test { 0: ::core::clone::Clone::clone(__field_0) }, } } } @@ -103,7 +103,7 @@ fn where_() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0, ref __field_1) => Test(::core::clone::Clone::clone(__field_0), ::core::clone::Clone::clone(__field_1)), + Test(ref __field_0, ref __field_1) => Test { 0: ::core::clone::Clone::clone(__field_0), 1: ::core::clone::Clone::clone(__field_1) }, } } } @@ -128,7 +128,10 @@ fn for_lifetime() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0, ref __field_1) => Test(::core::clone::Clone::clone(__field_0), ::core::clone::Clone::clone(__field_1)), + Test(ref __field_0, ref __field_1) => Test { + 0: ::core::clone::Clone::clone(__field_0), + 1: ::core::clone::Clone::clone(__field_1) + }, } } } @@ -151,7 +154,7 @@ fn associated_type() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0) => Test(::core::clone::Clone::clone(__field_0)), + Test(ref __field_0) => Test { 0: ::core::clone::Clone::clone(__field_0) }, } } } @@ -174,7 +177,7 @@ fn associated_type_custom_bound() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0) => Test(::core::clone::Clone::clone(__field_0)), + Test(ref __field_0) => Test { 0: ::core::clone::Clone::clone(__field_0) }, } } } @@ -197,7 +200,7 @@ fn check_trait_bounds() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0, ref __field_1) => Test(::core::clone::Clone::clone(__field_0), ::core::clone::Clone::clone(__field_1)), + Test(ref __field_0, ref __field_1) => Test { 0: ::core::clone::Clone::clone(__field_0), 1: ::core::clone::Clone::clone(__field_1) }, } } } @@ -333,7 +336,7 @@ fn check_multiple_trait_bounds() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0, ref __field_1) => Test(::core::clone::Clone::clone(__field_0), ::core::clone::Clone::clone(__field_1)), + Test(ref __field_0, ref __field_1) => Test { 0: ::core::clone::Clone::clone(__field_0), 1: ::core::clone::Clone::clone(__field_1) }, } } } diff --git a/src/test/clone.rs b/src/test/clone.rs index fdaafdd..4a8bb0b 100644 --- a/src/test/clone.rs +++ b/src/test/clone.rs @@ -26,6 +26,54 @@ fn struct_() -> Result<()> { ) } +#[test] +fn skip_inner() -> Result<()> { + test_derive( + quote! { + #[derive_where(Clone)] + #[derive_where(skip_inner(Clone))] + struct Test { + field: std::marker::PhantomData, + } + }, + quote! { + #[automatically_derived] + impl ::core::clone::Clone for Test { + #[inline] + fn clone(&self) -> Self { + match self { + Test { field: ref __field_field } => Test { field: ::core::default::Default::default() }, + } + } + } + }, + ) +} + +#[test] +fn skip_field() -> Result<()> { + test_derive( + quote! { + #[derive_where(Clone)] + struct Test { + #[derive_where(skip(Clone))] + field: std::marker::PhantomData, + } + }, + quote! { + #[automatically_derived] + impl ::core::clone::Clone for Test { + #[inline] + fn clone(&self) -> Self { + match self { + Test { field: ref __field_field } => Test { field: ::core::default::Default::default() }, + } + } + } + }, + ) +} + #[test] fn tuple() -> Result<()> { test_derive( @@ -39,7 +87,7 @@ fn tuple() -> Result<()> { #[inline] fn clone(&self) -> Self { match self { - Test(ref __field_0) => Test(::core::clone::Clone::clone(__field_0)), + Test(ref __field_0) => Test { 0: ::core::clone::Clone::clone(__field_0) }, } } } @@ -68,8 +116,8 @@ fn enum_() -> Result<()> { match self { Test::A { field: ref __field_field } => Test::A { field: ::core::clone::Clone::clone(__field_field) }, Test::B { } => Test::B { }, - Test::C(ref __field_0) => Test::C(::core::clone::Clone::clone(__field_0)), - Test::D() => Test::D(), + Test::C(ref __field_0) => Test::C { 0: ::core::clone::Clone::clone(__field_0) }, + Test::D() => Test::D { }, Test::E => Test::E, } } diff --git a/src/trait_/clone.rs b/src/trait_/clone.rs index dd08a33..94592b3 100644 --- a/src/trait_/clone.rs +++ b/src/trait_/clone.rs @@ -5,7 +5,8 @@ use quote::quote; use syn::{TraitBound, TraitBoundModifier, TypeParamBound}; use crate::{ - Data, DataType, DeriveTrait, DeriveWhere, Item, SimpleType, SplitGenerics, Trait, TraitImpl, + data::Field, Data, DataType, DeriveTrait, DeriveWhere, Item, SimpleType, SplitGenerics, Trait, + TraitImpl, }; /// Dummy-struct implement [`Trait`] for [`Clone`](trait@std::clone::Clone). @@ -99,25 +100,26 @@ impl TraitImpl for Clone { } match data.simple_type() { - SimpleType::Struct(fields) => { + SimpleType::Struct(fields) | SimpleType::Tuple(fields) => { let self_pattern = &fields.self_pattern; let item_path = &data.path; - let self_ident = data.iter_self_ident(**trait_); - let fields = data.iter_field_ident(**trait_); let trait_path = trait_.path(); + let default_path = DeriveTrait::Default.path(); - quote! { - #self_pattern => #item_path { #(#fields: #trait_path::clone(#self_ident)),* }, - } - } - SimpleType::Tuple(fields) => { - let self_pattern = &fields.self_pattern; - let item_path = &data.path; - let self_ident = data.iter_self_ident(**trait_); - let trait_path = trait_.path(); + let fields = fields.fields.iter().map( + |field @ Field { + self_ident, member, .. + }| { + if field.skip(Trait::Clone) || data.skip(Trait::Clone) { + quote!(#member: #default_path::default()) + } else { + quote!(#member: #trait_path::clone(#self_ident)) + } + }, + ); quote! { - #self_pattern => #item_path(#(#trait_path::clone(#self_ident)),*), + #self_pattern => #item_path { #(#fields),* }, } } SimpleType::Unit(pattern) => { diff --git a/tests/skip/field_trait.rs b/tests/skip/field_trait.rs index 567b4bf..284b04a 100644 --- a/tests/skip/field_trait.rs +++ b/tests/skip/field_trait.rs @@ -4,7 +4,8 @@ use std::cmp::Ordering; use derive_where::derive_where; use crate::util::{ - self, AssertDebug, AssertHash, AssertOrd, AssertPartialEq, AssertPartialOrd, Wrapper, + self, AssertClone, AssertDebug, AssertHash, AssertOrd, AssertPartialEq, AssertPartialOrd, + NonTrait, Wrapper, }; #[test] @@ -19,6 +20,18 @@ fn debug() { assert_eq!(format!("{:?}", test_1), "Test"); } +#[test] +fn clone() { + #[derive_where(Clone)] + struct Test(#[derive_where(skip(Clone))] NonTrait); + + let test_1 = Test(42.into()); + + let _ = AssertClone(&test_1); + + assert_eq!(test_1.clone().0.data(), 0) +} + #[test] fn hash() { #[derive_where(Hash)] diff --git a/tests/skip/struct_trait.rs b/tests/skip/struct_trait.rs index e9df4a7..e998f35 100644 --- a/tests/skip/struct_trait.rs +++ b/tests/skip/struct_trait.rs @@ -4,7 +4,8 @@ use std::cmp::Ordering; use derive_where::derive_where; use crate::util::{ - self, AssertDebug, AssertHash, AssertOrd, AssertPartialEq, AssertPartialOrd, Wrapper, + self, AssertClone, AssertDebug, AssertHash, AssertOrd, AssertPartialEq, AssertPartialOrd, + NonTrait, Wrapper, }; #[test] @@ -20,6 +21,19 @@ fn debug() { assert_eq!(format!("{:?}", test_1), "Test"); } +#[test] +fn clone() { + #[derive_where(Clone)] + #[derive_where(skip_inner(Clone))] + struct Test(NonTrait); + + let test_1 = Test(42.into()); + + let _ = AssertClone(&test_1); + + assert_eq!(test_1.clone().0.data(), 0); +} + #[test] fn hash() { #[derive_where(Hash)] @@ -67,21 +81,24 @@ fn ord() { #[test] fn all() { - #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[derive_where(skip_inner(Debug, EqHashOrd))] - struct Test(Wrapper); + #[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] + #[derive_where(skip_inner(Clone, Debug, EqHashOrd))] + struct Test(NonTrait); let test_1 = Test(42.into()); let test_2 = Test(42.into()); let test_le = Test(41.into()); let test_ge = Test(43.into()); + let _ = AssertClone(&test_1); let _ = AssertDebug(&test_1); let _ = AssertHash(&test_1); let _ = AssertOrd(&test_1); let _ = AssertPartialEq(&test_1); let _ = AssertPartialOrd(&test_1); + assert_eq!(test_1.clone().0.data(), 0); + assert_eq!(format!("{:?}", test_1), "Test"); util::hash_eq(&test_1, &test_2); diff --git a/tests/skip/variant_trait.rs b/tests/skip/variant_trait.rs index 83ab7c3..e53a225 100644 --- a/tests/skip/variant_trait.rs +++ b/tests/skip/variant_trait.rs @@ -2,9 +2,11 @@ use std::cmp::Ordering; use derive_where::derive_where; +use pretty_assertions::assert_eq; use crate::util::{ - self, AssertDebug, AssertHash, AssertOrd, AssertPartialEq, AssertPartialOrd, Wrapper, + self, AssertClone, AssertDebug, AssertHash, AssertOrd, AssertPartialEq, AssertPartialOrd, + NonTrait, Wrapper, }; #[test] @@ -22,6 +24,22 @@ fn debug() { assert_eq!(format!("{:?}", test_1), "A"); } +#[test] +fn clone() { + #[derive_where(Clone)] + enum Test { + #[derive_where(skip_inner(Clone))] + A(NonTrait), + } + + let test_1 = Test::A(42.into()); + + let _ = AssertClone(&test_1); + + let Test::A(cloned) = test_1.clone(); + assert_eq!(cloned.data(), 0); +} + #[test] fn hash() { #[derive_where(Hash)] @@ -73,9 +91,9 @@ fn ord() { #[test] fn all() { - #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] + #[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Clone)] enum Test { - #[derive_where(skip_inner(Debug, EqHashOrd))] + #[derive_where(skip_inner(Debug, EqHashOrd, Clone))] A(Wrapper), } @@ -85,6 +103,7 @@ fn all() { let test_ge = Test::A(43.into()); let _ = AssertDebug(&test_1); + let _ = AssertClone(&test_1); let _ = AssertHash(&test_1); let _ = AssertOrd(&test_1); let _ = AssertPartialEq(&test_1); @@ -92,6 +111,8 @@ fn all() { assert_eq!(format!("{:?}", test_1), "A"); + assert_eq!(test_1.clone(), Test::A(0.into())); + util::hash_eq(&test_1, &test_2); util::hash_eq(&test_1, &test_ge); diff --git a/tests/ui/not-zeroize/item_skip.rs b/tests/ui/not-zeroize/item_skip.rs index aebf803..3a9464c 100644 --- a/tests/ui/not-zeroize/item_skip.rs +++ b/tests/ui/not-zeroize/item_skip.rs @@ -2,8 +2,8 @@ use std::marker::PhantomData; use derive_where::derive_where; -#[derive_where(Clone; T)] -#[derive_where(skip_inner(Clone))] +#[derive_where(Copy; T)] +#[derive_where(skip_inner(Copy))] struct UnsupportedTrait(PhantomData); fn main() {} diff --git a/tests/ui/not-zeroize/item_skip.stderr b/tests/ui/not-zeroize/item_skip.stderr index f2faddb..de66a5e 100644 --- a/tests/ui/not-zeroize/item_skip.stderr +++ b/tests/ui/not-zeroize/item_skip.stderr @@ -1,5 +1,5 @@ -error: unsupported skip group, expected one of Debug, EqHashOrd, Hash +error: unsupported skip group, expected one of Clone, Debug, EqHashOrd, Hash --> tests/ui/not-zeroize/item_skip.rs:6:27 | -6 | #[derive_where(skip_inner(Clone))] - | ^^^^^ +6 | #[derive_where(skip_inner(Copy))] + | ^^^^ diff --git a/tests/ui/not-zeroize/skip.rs b/tests/ui/not-zeroize/skip.rs index c4e6a32..f8f861d 100644 --- a/tests/ui/not-zeroize/skip.rs +++ b/tests/ui/not-zeroize/skip.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use derive_where::derive_where; -#[derive_where(Clone; T)] -struct UnsupportedTrait(#[derive_where(skip(Clone))] PhantomData); +#[derive_where(Copy; T)] +struct UnsupportedTrait(#[derive_where(skip(Copy))] PhantomData); fn main() {} diff --git a/tests/ui/not-zeroize/skip.stderr b/tests/ui/not-zeroize/skip.stderr index 99105e4..44e0213 100644 --- a/tests/ui/not-zeroize/skip.stderr +++ b/tests/ui/not-zeroize/skip.stderr @@ -1,5 +1,5 @@ -error: unsupported skip group, expected one of Debug, EqHashOrd, Hash +error: unsupported skip group, expected one of Clone, Debug, EqHashOrd, Hash --> tests/ui/not-zeroize/skip.rs:6:48 | -6 | struct UnsupportedTrait(#[derive_where(skip(Clone))] PhantomData); - | ^^^^^ +6 | struct UnsupportedTrait(#[derive_where(skip(Copy))] PhantomData); + | ^^^^ diff --git a/tests/ui/skip.rs b/tests/ui/skip.rs index 40a7742..bd367bb 100644 --- a/tests/ui/skip.rs +++ b/tests/ui/skip.rs @@ -45,4 +45,13 @@ struct DuplicateTraitSeparate( #[derive_where(Clone; T)] struct MissingDeriveTrait(#[derive_where(skip(Debug))] PhantomData); +#[derive_where(Clone, Copy)] +struct SkipCloneWhileCopy(#[derive_where(skip(Clone))] PhantomData); + +struct NonDefault(PhantomData); + +#[derive_where(Clone)] +#[derive_where(skip_inner(Clone))] +struct SkipCloneNonDefault(NonDefault); + fn main() {} diff --git a/tests/ui/skip.stderr b/tests/ui/skip.stderr index eadeee4..a22e765 100644 --- a/tests/ui/skip.stderr +++ b/tests/ui/skip.stderr @@ -51,3 +51,22 @@ error: trait to be skipped isn't being implemented | 46 | struct MissingDeriveTrait(#[derive_where(skip(Debug))] PhantomData); | ^^^^^ + +error: Cannot skip `Clone` while deriving `Copy` + --> tests/ui/skip.rs:49:50 + | +49 | struct SkipCloneWhileCopy(#[derive_where(skip(Clone))] PhantomData); + | ^^^^^ + +error[E0277]: the trait bound `NonDefault: Default` is not satisfied + --> tests/ui/skip.rs:53:1 + | +53 | #[derive_where(Clone)] + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `NonDefault` + | + = note: this error originates in the derive macro `::derive_where::DeriveWhere` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NonDefault` with `#[derive(Default)]` + | +51 + #[derive(Default)] +52 | struct NonDefault(PhantomData); + | diff --git a/tests/ui/zeroize/item_skip.rs b/tests/ui/zeroize/item_skip.rs index aebf803..3a9464c 100644 --- a/tests/ui/zeroize/item_skip.rs +++ b/tests/ui/zeroize/item_skip.rs @@ -2,8 +2,8 @@ use std::marker::PhantomData; use derive_where::derive_where; -#[derive_where(Clone; T)] -#[derive_where(skip_inner(Clone))] +#[derive_where(Copy; T)] +#[derive_where(skip_inner(Copy))] struct UnsupportedTrait(PhantomData); fn main() {} diff --git a/tests/ui/zeroize/item_skip.stderr b/tests/ui/zeroize/item_skip.stderr index 2723f95..9f8ec6f 100644 --- a/tests/ui/zeroize/item_skip.stderr +++ b/tests/ui/zeroize/item_skip.stderr @@ -1,5 +1,5 @@ -error: unsupported skip group, expected one of Debug, EqHashOrd, Hash, Zeroize +error: unsupported skip group, expected one of Clone, Debug, EqHashOrd, Hash, Zeroize --> tests/ui/zeroize/item_skip.rs:6:27 | -6 | #[derive_where(skip_inner(Clone))] - | ^^^^^ +6 | #[derive_where(skip_inner(Copy))] + | ^^^^ diff --git a/tests/ui/zeroize/skip.rs b/tests/ui/zeroize/skip.rs index c4e6a32..6f866f0 100644 --- a/tests/ui/zeroize/skip.rs +++ b/tests/ui/zeroize/skip.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use derive_where::derive_where; -#[derive_where(Clone; T)] -struct UnsupportedTrait(#[derive_where(skip(Clone))] PhantomData); +#[derive_where(Skip; T)] +struct UnsupportedTrait(#[derive_where(skip(Skip))] PhantomData); fn main() {} diff --git a/tests/ui/zeroize/skip.stderr b/tests/ui/zeroize/skip.stderr index 4dddf78..acc20ba 100644 --- a/tests/ui/zeroize/skip.stderr +++ b/tests/ui/zeroize/skip.stderr @@ -1,5 +1,5 @@ -error: unsupported skip group, expected one of Debug, EqHashOrd, Hash, Zeroize - --> tests/ui/zeroize/skip.rs:6:48 +error: unsupported trait, expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize, ZeroizeOnDrop + --> tests/ui/zeroize/skip.rs:5:16 | -6 | struct UnsupportedTrait(#[derive_where(skip(Clone))] PhantomData); - | ^^^^^ +5 | #[derive_where(Skip; T)] + | ^^^^ diff --git a/tests/util/mod.rs b/tests/util/mod.rs index d228d10..d2f1eb7 100644 --- a/tests/util/mod.rs +++ b/tests/util/mod.rs @@ -121,6 +121,37 @@ pub struct AssertZeroize<'a, T: Zeroize>(pub &'a T); #[allow(dead_code)] pub struct AssertZeroizeOnDrop<'a, T: ZeroizeOnDrop>(pub &'a T); +#[allow(dead_code)] +pub struct NonTrait { + data: i32, + hack: PhantomData, +} + +#[allow(dead_code)] +impl NonTrait { + pub fn data(&self) -> i32 { + self.data + } +} + +impl Default for NonTrait { + fn default() -> Self { + Self { + data: i32::default(), + hack: PhantomData, + } + } +} + +impl From for NonTrait<()> { + fn from(data: i32) -> Self { + Self { + data, + hack: PhantomData, + } + } +} + #[allow(dead_code)] pub fn hash_eq(test_1: T, test_2: T) { let mut hasher = DefaultHasher::new();