From bb67a7b4ddffb8ba6cd6266cee19175e0109f05a Mon Sep 17 00:00:00 2001 From: Ada Bohm Date: Tue, 24 Feb 2026 12:03:48 +0100 Subject: [PATCH 1/6] Generate shortcut for Clone and Ord only when all generics are custom bound --- src/attr/item.rs | 8 ++++++++ src/trait_/clone.rs | 8 ++------ src/trait_/partial_ord.rs | 7 ++----- tests/bound.rs | 14 ++++++++++++++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/attr/item.rs b/src/attr/item.rs index adea6e5b..4c3547f9 100644 --- a/src/attr/item.rs +++ b/src/attr/item.rs @@ -238,6 +238,14 @@ impl DeriveWhere { }) } + /// Returns `true` if all [`Generic`] are [`CustomBound`](Generic::CustomBound), + pub fn all_custom_bound(&self) -> bool { + self.generics.iter().all(|generic| match generic { + Generic::CustomBound(_) => true, + Generic::NoBound(_) => false, + }) + } + /// Returns `true` if the given generic type parameter if present. pub fn has_type_param(&self, type_param: &Ident) -> bool { self.generics.iter().any(|generic| match generic { diff --git a/src/trait_/clone.rs b/src/trait_/clone.rs index 9b15f4c8..9e047d98 100644 --- a/src/trait_/clone.rs +++ b/src/trait_/clone.rs @@ -57,9 +57,7 @@ impl TraitImpl for Clone { body: &TokenStream, ) -> TokenStream { // Special implementation for items also implementing `Copy`. - if (derive_where.generics.is_empty() || derive_where.any_custom_bound()) - && derive_where.contains(Trait::Copy) - { + if (derive_where.all_custom_bound()) && derive_where.contains(Trait::Copy) { return quote! { #[inline] fn clone(&self) -> Self { *self } @@ -93,9 +91,7 @@ impl TraitImpl for Clone { } fn build_body(&self, derive_where: &DeriveWhere, data: &Data) -> TokenStream { - if (derive_where.generics.is_empty() || derive_where.any_custom_bound()) - && derive_where.contains(Trait::Copy) - { + if (derive_where.all_custom_bound()) && derive_where.contains(Trait::Copy) { return TokenStream::new(); } diff --git a/src/trait_/partial_ord.rs b/src/trait_/partial_ord.rs index 19f4f15f..75a69a01 100644 --- a/src/trait_/partial_ord.rs +++ b/src/trait_/partial_ord.rs @@ -33,9 +33,7 @@ impl TraitImpl for PartialOrd { generics: &SplitGenerics<'_>, body: &TokenStream, ) -> TokenStream { - let body = if (derive_where.generics.is_empty() || derive_where.any_custom_bound()) - && derive_where.contains(Trait::Ord) - { + let body = if (derive_where.all_custom_bound()) && derive_where.contains(Trait::Ord) { quote! { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, __other)) } @@ -54,8 +52,7 @@ impl TraitImpl for PartialOrd { fn build_body(&self, derive_where: &DeriveWhere, data: &Data) -> TokenStream { if data.is_empty(**self) || data.is_incomparable() - || ((derive_where.generics.is_empty() || derive_where.any_custom_bound()) - && derive_where.contains(Trait::Ord)) + || (derive_where.all_custom_bound() && derive_where.contains(Trait::Ord)) { TokenStream::new() } else { diff --git a/tests/bound.rs b/tests/bound.rs index 7b20ce8c..bd11cbaa 100644 --- a/tests/bound.rs +++ b/tests/bound.rs @@ -81,3 +81,17 @@ fn ord_requirement() { #[derive_where(Eq, Ord, PartialEq, PartialOrd; T::Type)] struct Test(T::Type); } + +#[test] +fn ord_and_partial_ord() { + trait Trait {} + #[derive_where(PartialOrd, Ord, PartialEq, Eq; I: Trait, T)] + struct Foo(T, PhantomData); +} + +#[test] +fn copy_and_clone() { + trait Trait {} + #[derive_where(Copy, Clone; I: Trait, T)] + struct Foo(T, PhantomData); +} From cde628d60818fd8c1147b65ffcaadfd1dfee6373 Mon Sep 17 00:00:00 2001 From: Ada Bohm Date: Thu, 26 Feb 2026 08:39:45 +0100 Subject: [PATCH 2/6] Formatting fixed --- src/attr/item.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/attr/item.rs b/src/attr/item.rs index 4c3547f9..874d8bf7 100644 --- a/src/attr/item.rs +++ b/src/attr/item.rs @@ -238,7 +238,8 @@ impl DeriveWhere { }) } - /// Returns `true` if all [`Generic`] are [`CustomBound`](Generic::CustomBound), + /// Returns `true` if all [`Generic`] are + /// [`CustomBound`](Generic::CustomBound) pub fn all_custom_bound(&self) -> bool { self.generics.iter().all(|generic| match generic { Generic::CustomBound(_) => true, From be285d75ff9d7fdd574d04b161c3e6c230c23891 Mon Sep 17 00:00:00 2001 From: Ada Bohm Date: Thu, 26 Feb 2026 08:44:57 +0100 Subject: [PATCH 3/6] unicode-ident pinning for CI tests --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c45a8282..b2e09c7f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,6 +67,7 @@ jobs: cargo update -p glob --precise 0.3.2 cargo update -p proc-macro2 --precise 1.0.80 cargo update -p quote --precise 1.0.35 + cargo update -p unicode-ident --precise 1.0.22 - name: Build run: cargo build --workspace ${{ matrix.features }} @@ -130,6 +131,7 @@ jobs: cargo update -p pretty_assertions --precise 1.4.0 cargo update -p proc-macro2 --precise 1.0.80 cargo update -p quote --precise 1.0.35 + cargo update -p unicode-ident --precise 1.0.22 - name: Build run: cargo build --target thumbv6m-none-eabi ${{ matrix.features }} -p ensure-no-std From e7108e2a7933f9fa411b388cc48627deefe66a2b Mon Sep 17 00:00:00 2001 From: Ada Bohm Date: Fri, 27 Feb 2026 12:57:17 +0100 Subject: [PATCH 4/6] Addition version pinning in CI --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b2e09c7f..736b0a66 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -68,6 +68,8 @@ jobs: cargo update -p proc-macro2 --precise 1.0.80 cargo update -p quote --precise 1.0.35 cargo update -p unicode-ident --precise 1.0.22 + cargo update -p ryu --precise 1.0.20 + cargo update -p itoa --precise 1.0.15 - name: Build run: cargo build --workspace ${{ matrix.features }} @@ -132,6 +134,8 @@ jobs: cargo update -p proc-macro2 --precise 1.0.80 cargo update -p quote --precise 1.0.35 cargo update -p unicode-ident --precise 1.0.22 + cargo update -p ryu --precise 1.0.20 + cargo update -p itoa --precise 1.0.15 - name: Build run: cargo build --target thumbv6m-none-eabi ${{ matrix.features }} -p ensure-no-std From 4e9eeb1ec835727554c67216f6220c798b0a3eec Mon Sep 17 00:00:00 2001 From: Ada Bohm Date: Thu, 5 Mar 2026 10:57:18 +0100 Subject: [PATCH 5/6] Updated UI test on nightly --- tests/ui/union.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/union.stderr b/tests/ui/union.stderr index 177941ee..7f4806ec 100644 --- a/tests/ui/union.stderr +++ b/tests/ui/union.stderr @@ -6,11 +6,11 @@ error: traits other then `Clone` and `Copy` aren't supported by unions 8 | | } | |_^ -error[E0277]: the trait bound `MissingCopy: std::marker::Copy` is not satisfied +error[E0277]: the trait bound `MissingCopy: Copy` is not satisfied --> tests/ui/union.rs:10:1 | 10 | #[derive_where(Clone)] - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `MissingCopy` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `MissingCopy` | note: required by a bound in `__AssertCopy` --> tests/ui/union.rs:10:1 From aca660eb98a27113fe96958bfbfe1a736808896c Mon Sep 17 00:00:00 2001 From: Ada Bohm Date: Sat, 7 Mar 2026 21:21:09 +0100 Subject: [PATCH 6/6] Updated ui test for zeroize-on-drop --- tests/ui/zeroize-on-drop/zeroize-on-drop.stderr | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/ui/zeroize-on-drop/zeroize-on-drop.stderr b/tests/ui/zeroize-on-drop/zeroize-on-drop.stderr index 989b5a3a..798f5712 100644 --- a/tests/ui/zeroize-on-drop/zeroize-on-drop.stderr +++ b/tests/ui/zeroize-on-drop/zeroize-on-drop.stderr @@ -16,10 +16,11 @@ note: the following trait bounds were not satisfied: --> tests/ui/zeroize-on-drop/zeroize-on-drop.rs:10:1 | 10 | #[derive_where(ZeroizeOnDrop(no_drop))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter would need to implement `AssertZeroizeOnDrop` + = help: consider manually implementing the trait to avoid undesired bounds = help: items from traits can only be used if the type parameter is bounded by the trait - = note: this error originates in the derive macro `::derive_where::DeriveWhere` which comes from the expansion of the attribute macro `derive_where` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the derive macro `::derive_where::DeriveWhere` (in Nightly builds, run with -Z macro-backtrace for more info) help: the following trait defines an item `__derive_where_zeroize_on_drop`, perhaps you need to restrict type parameter `T` with it: | -11 | struct NoDropNoZeroizeOnDrop as DeriveWhereAssertZeroizeOnDrop>::assert::AssertZeroizeOnDrop>(T); - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +11 | struct NoDropNoZeroizeOnDrop(T); + | +++++++++++++++++++++