Skip to content

Commit c8205c3

Browse files
committed
Fix PartialOrd implementations when using bounds
1 parent 0930cb0 commit c8205c3

File tree

15 files changed

+101
-15
lines changed

15 files changed

+101
-15
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Fixed
11+
- Don't use `Ord` in `PartialOrd` implementations if using any bounds.
12+
813
## [1.2.2] - 2023-08-22
914

1015
### Fixed

src/lib.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ fn generate_impl(
628628
let mut where_clause = where_clause.map(Cow::Borrowed);
629629
derive_where.where_clause(&mut where_clause, trait_, item);
630630

631-
let body = generate_body(&derive_where.traits, trait_, item);
631+
let body = generate_body(derive_where, &derive_where.traits, trait_, item);
632632

633633
let ident = item.ident();
634634
let path = trait_.impl_path(trait_);
@@ -654,19 +654,26 @@ fn generate_impl(
654654
}
655655

656656
/// Generate implementation method body for a [`Trait`].
657-
fn generate_body(traits: &[DeriveTrait], trait_: &DeriveTrait, item: &Item) -> TokenStream {
657+
fn generate_body(
658+
derive_where: &DeriveWhere,
659+
traits: &[DeriveTrait],
660+
trait_: &DeriveTrait,
661+
item: &Item,
662+
) -> TokenStream {
663+
let any_bound = !derive_where.generics.is_empty();
664+
658665
match &item {
659666
Item::Item(data) => {
660-
let body = trait_.build_body(traits, trait_, data);
661-
trait_.build_signature(item, traits, trait_, &body)
667+
let body = trait_.build_body(any_bound, traits, trait_, data);
668+
trait_.build_signature(any_bound, item, traits, trait_, &body)
662669
}
663670
Item::Enum { variants, .. } => {
664671
let body: TokenStream = variants
665672
.iter()
666-
.map(|data| trait_.build_body(traits, trait_, data))
673+
.map(|data| trait_.build_body(any_bound, traits, trait_, data))
667674
.collect();
668675

669-
trait_.build_signature(item, traits, trait_, &body)
676+
trait_.build_signature(any_bound, item, traits, trait_, &body)
670677
}
671678
}
672679
}

src/test/bound.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,16 @@ fn check_trait_bounds() -> Result<()> {
246246
{
247247
#[inline]
248248
fn partial_cmp(&self, __other: &Self) -> ::core::option::Option<::core::cmp::Ordering> {
249-
::core::option::Option::Some(::core::cmp::Ord::cmp(self, __other))
249+
match (self, __other) {
250+
(Test(ref __field_0, ref __field_1), Test(ref __other_field_0, ref __other_field_1)) =>
251+
match ::core::cmp::PartialOrd::partial_cmp(__field_0, __other_field_0) {
252+
::core::option::Option::Some(::core::cmp::Ordering::Equal) => match ::core::cmp::PartialOrd::partial_cmp(__field_1, __other_field_1) {
253+
::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal),
254+
__cmp => __cmp,
255+
},
256+
__cmp => __cmp,
257+
},
258+
}
250259
}
251260
}
252261
},
@@ -378,7 +387,16 @@ fn check_multiple_trait_bounds() -> Result<()> {
378387
{
379388
#[inline]
380389
fn partial_cmp(&self, __other: &Self) -> ::core::option::Option<::core::cmp::Ordering> {
381-
::core::option::Option::Some(::core::cmp::Ord::cmp(self, __other))
390+
match (self, __other) {
391+
(Test(ref __field_0, ref __field_1), Test(ref __other_field_0, ref __other_field_1)) =>
392+
match ::core::cmp::PartialOrd::partial_cmp(__field_0, __other_field_0) {
393+
::core::option::Option::Some(::core::cmp::Ordering::Equal) => match ::core::cmp::PartialOrd::partial_cmp(__field_1, __other_field_1) {
394+
::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal),
395+
__cmp => __cmp,
396+
},
397+
__cmp => __cmp,
398+
},
399+
}
382400
}
383401
}
384402
},

src/trait_.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,17 +133,25 @@ impl TraitImpl for Trait {
133133

134134
fn build_signature(
135135
&self,
136+
any_bound: bool,
136137
item: &Item,
137138
traits: &[DeriveTrait],
138139
trait_: &DeriveTrait,
139140
body: &TokenStream,
140141
) -> TokenStream {
141142
self.implementation()
142-
.build_signature(item, traits, trait_, body)
143+
.build_signature(any_bound, item, traits, trait_, body)
143144
}
144145

145-
fn build_body(&self, traits: &[DeriveTrait], trait_: &DeriveTrait, data: &Data) -> TokenStream {
146-
self.implementation().build_body(traits, trait_, data)
146+
fn build_body(
147+
&self,
148+
any_bound: bool,
149+
traits: &[DeriveTrait],
150+
trait_: &DeriveTrait,
151+
data: &Data,
152+
) -> TokenStream {
153+
self.implementation()
154+
.build_body(any_bound, traits, trait_, data)
147155
}
148156
}
149157

@@ -190,6 +198,7 @@ pub trait TraitImpl {
190198
/// Build method signature for this [`Trait`].
191199
fn build_signature(
192200
&self,
201+
_any_bound: bool,
193202
_item: &Item,
194203
_traits: &[DeriveTrait],
195204
_trait_: &DeriveTrait,
@@ -201,6 +210,7 @@ pub trait TraitImpl {
201210
/// Build method body for this [`Trait`].
202211
fn build_body(
203212
&self,
213+
_any_bound: bool,
204214
_traits: &[DeriveTrait],
205215
_trait_: &DeriveTrait,
206216
_data: &Data,

src/trait_/clone.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ impl TraitImpl for Clone {
4242

4343
fn build_signature(
4444
&self,
45+
_any_bound: bool,
4546
item: &Item,
4647
traits: &[DeriveTrait],
4748
_trait_: &DeriveTrait,
@@ -81,7 +82,13 @@ impl TraitImpl for Clone {
8182
}
8283
}
8384

84-
fn build_body(&self, traits: &[DeriveTrait], trait_: &DeriveTrait, data: &Data) -> TokenStream {
85+
fn build_body(
86+
&self,
87+
_any_bound: bool,
88+
traits: &[DeriveTrait],
89+
trait_: &DeriveTrait,
90+
data: &Data,
91+
) -> TokenStream {
8592
if traits.iter().any(|trait_| trait_ == Trait::Copy) {
8693
return TokenStream::new();
8794
}

src/trait_/debug.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ impl TraitImpl for Debug {
2020

2121
fn build_signature(
2222
&self,
23+
_any_bound: bool,
2324
_item: &Item,
2425
_traits: &[DeriveTrait],
2526
_trait_: &DeriveTrait,
@@ -36,6 +37,7 @@ impl TraitImpl for Debug {
3637

3738
fn build_body(
3839
&self,
40+
_any_bound: bool,
3941
_traits: &[DeriveTrait],
4042
trait_: &DeriveTrait,
4143
data: &Data,

src/trait_/default.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ impl TraitImpl for Default {
2020

2121
fn build_signature(
2222
&self,
23+
_any_bound: bool,
2324
_item: &Item,
2425
_traits: &[DeriveTrait],
2526
_trait_: &DeriveTrait,
@@ -34,6 +35,7 @@ impl TraitImpl for Default {
3435

3536
fn build_body(
3637
&self,
38+
_any_bound: bool,
3739
_traits: &[DeriveTrait],
3840
trait_: &DeriveTrait,
3941
data: &Data,

src/trait_/eq.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ impl TraitImpl for Eq {
2020

2121
fn build_signature(
2222
&self,
23+
_any_bound: bool,
2324
_item: &Item,
2425
_traits: &[DeriveTrait],
2526
_trait_: &DeriveTrait,
@@ -37,6 +38,7 @@ impl TraitImpl for Eq {
3738

3839
fn build_body(
3940
&self,
41+
_any_bound: bool,
4042
_traits: &[DeriveTrait],
4143
trait_: &DeriveTrait,
4244
data: &Data,

src/trait_/hash.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ impl TraitImpl for Hash {
2020

2121
fn build_signature(
2222
&self,
23+
_any_bound: bool,
2324
_item: &Item,
2425
_traits: &[DeriveTrait],
2526
_trait_: &DeriveTrait,
@@ -36,6 +37,7 @@ impl TraitImpl for Hash {
3637

3738
fn build_body(
3839
&self,
40+
_any_bound: bool,
3941
_traits: &[DeriveTrait],
4042
trait_: &DeriveTrait,
4143
data: &Data,

src/trait_/ord.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ impl TraitImpl for Ord {
2121

2222
fn build_signature(
2323
&self,
24+
_any_bound: bool,
2425
item: &Item,
2526
_traits: &[DeriveTrait],
2627
trait_: &DeriveTrait,
@@ -38,6 +39,7 @@ impl TraitImpl for Ord {
3839

3940
fn build_body(
4041
&self,
42+
_any_bound: bool,
4143
_traits: &[DeriveTrait],
4244
trait_: &DeriveTrait,
4345
data: &Data,

src/trait_/partial_eq.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ impl TraitImpl for PartialEq {
2121

2222
fn build_signature(
2323
&self,
24+
_any_bound: bool,
2425
item: &Item,
2526
_traits: &[DeriveTrait],
2627
trait_: &DeriveTrait,
@@ -105,6 +106,7 @@ impl TraitImpl for PartialEq {
105106

106107
fn build_body(
107108
&self,
109+
_any_bound: bool,
108110
_traits: &[DeriveTrait],
109111
trait_: &DeriveTrait,
110112
data: &Data,

src/trait_/partial_ord.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ impl TraitImpl for PartialOrd {
2121

2222
fn build_signature(
2323
&self,
24+
any_bound: bool,
2425
item: &Item,
2526
traits: &[DeriveTrait],
2627
trait_: &DeriveTrait,
2728
body: &TokenStream,
2829
) -> TokenStream {
29-
let body = if traits.iter().any(|trait_| trait_ == Trait::Ord) {
30+
let body = if !any_bound && traits.iter().any(|trait_| trait_ == Trait::Ord) {
3031
quote! {
3132
::core::option::Option::Some(::core::cmp::Ord::cmp(self, __other))
3233
}
@@ -42,10 +43,16 @@ impl TraitImpl for PartialOrd {
4243
}
4344
}
4445

45-
fn build_body(&self, traits: &[DeriveTrait], trait_: &DeriveTrait, data: &Data) -> TokenStream {
46+
fn build_body(
47+
&self,
48+
any_bound: bool,
49+
traits: &[DeriveTrait],
50+
trait_: &DeriveTrait,
51+
data: &Data,
52+
) -> TokenStream {
4653
if data.is_empty(**trait_)
4754
|| data.is_incomparable()
48-
|| traits.iter().any(|trait_| trait_ == Trait::Ord)
55+
|| (!any_bound && traits.iter().any(|trait_| trait_ == Trait::Ord))
4956
{
5057
TokenStream::new()
5158
} else {

src/trait_/zeroize.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ impl TraitImpl for Zeroize {
7979

8080
fn build_signature(
8181
&self,
82+
_any_bound: bool,
8283
item: &Item,
8384
_traits: &[DeriveTrait],
8485
trait_: &DeriveTrait,
@@ -105,6 +106,7 @@ impl TraitImpl for Zeroize {
105106

106107
fn build_body(
107108
&self,
109+
_any_bound: bool,
108110
_traits: &[DeriveTrait],
109111
trait_: &DeriveTrait,
110112
data: &Data,

src/trait_/zeroize_on_drop.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ impl TraitImpl for ZeroizeOnDrop {
8585

8686
fn build_signature(
8787
&self,
88+
_any_bound: bool,
8889
item: &Item,
8990
_traits: &[DeriveTrait],
9091
trait_: &DeriveTrait,
@@ -133,6 +134,7 @@ impl TraitImpl for ZeroizeOnDrop {
133134

134135
fn build_body(
135136
&self,
137+
_any_bound: bool,
136138
_traits: &[DeriveTrait],
137139
trait_: &DeriveTrait,
138140
data: &Data,

tests/bound.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,19 @@ fn custom_bound() {
4949
let test_clone = test_1.clone();
5050
assert_eq!(test_clone.0, 42);
5151
}
52+
53+
#[test]
54+
fn ord_requirement() {
55+
trait Trait {
56+
type Type;
57+
}
58+
59+
struct Impl;
60+
61+
impl Trait for Impl {
62+
type Type = i32;
63+
}
64+
65+
#[derive_where(Eq, Ord, PartialEq, PartialOrd; T::Type)]
66+
struct Test<T: Trait>(T::Type);
67+
}

0 commit comments

Comments
 (0)