From 0d71d3c685f2e23b1ad209b48408efe1205b18b0 Mon Sep 17 00:00:00 2001 From: Matteo Zeggiotti Date: Fri, 19 Jun 2026 10:50:09 +0200 Subject: [PATCH 1/4] Fixed key comparison Key comparison was borken between 'static and generic 'a str --- src/kv/key.rs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index 12ee16a82..eed686cf4 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -34,7 +34,7 @@ impl ToKey for str { /// A key in a key-value. // These impls must only be based on the as_str() representation of the key // If a new field (such as an optional index) is added to the key they must not affect comparison -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Debug, Eq, Ord, Hash)] pub struct Key<'k> { key: MaybeStaticStr<'k>, } @@ -107,6 +107,18 @@ impl<'k> From<&'k str> for Key<'k> { } } +impl PartialEq for Key<'_> { + fn eq(&self, other: &Self) -> bool { + self.key.get() == other.key.get() + } +} + +impl PartialOrd for Key<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.key.get().cmp(other.key.get())) + } +} + #[cfg(feature = "std")] mod std_support { use super::*; @@ -178,4 +190,24 @@ mod tests { fn key_to_borrowed() { assert_eq!("a key", Key::from_str("a key").to_borrowed_str().unwrap()); } + + #[test] + fn key_static_eq() { + assert_eq!(Key::from_str_static("a key"), Key::from_str_static("a key")); + } + + #[test] + fn key_borrowed_eq() { + let k1 = String::from("a key"); + let k2 = String::from("a key"); + assert_eq!(Key::from_str(&k1), Key::from_str(&k2)); + } + + #[test] + fn key_borrowed_and_static_eq() { + const KEY: &str = "a key"; + let static_key = Key::from_str_static(KEY); + let borrowed_key = Key::from_str("a key"); + assert_eq!(static_key, borrowed_key); + } } From 920e7dc2811c18a228bf78e818196de950659d85 Mon Sep 17 00:00:00 2001 From: Matteo Zeggiotti Date: Fri, 19 Jun 2026 11:57:44 +0200 Subject: [PATCH 2/4] Review: fixed comparison on `MaybeStaticStr` --- src/kv/key.rs | 21 +++++---------------- src/lib.rs | 14 +++++++++++++- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index eed686cf4..ae44fbba1 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -34,7 +34,7 @@ impl ToKey for str { /// A key in a key-value. // These impls must only be based on the as_str() representation of the key // If a new field (such as an optional index) is added to the key they must not affect comparison -#[derive(Clone, Debug, Eq, Ord, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Key<'k> { key: MaybeStaticStr<'k>, } @@ -107,18 +107,6 @@ impl<'k> From<&'k str> for Key<'k> { } } -impl PartialEq for Key<'_> { - fn eq(&self, other: &Self) -> bool { - self.key.get() == other.key.get() - } -} - -impl PartialOrd for Key<'_> { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.key.get().cmp(other.key.get())) - } -} - #[cfg(feature = "std")] mod std_support { use super::*; @@ -198,8 +186,9 @@ mod tests { #[test] fn key_borrowed_eq() { - let k1 = String::from("a key"); - let k2 = String::from("a key"); + const KEY: &str = "a key"; + let k1 = String::from(KEY); + let k2 = String::from(KEY); assert_eq!(Key::from_str(&k1), Key::from_str(&k2)); } @@ -207,7 +196,7 @@ mod tests { fn key_borrowed_and_static_eq() { const KEY: &str = "a key"; let static_key = Key::from_str_static(KEY); - let borrowed_key = Key::from_str("a key"); + let borrowed_key = Key::from_str(KEY); assert_eq!(static_key, borrowed_key); } } diff --git a/src/lib.rs b/src/lib.rs index 1682869a6..442e169b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -777,7 +777,7 @@ impl LevelFilter { } } -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +#[derive(Copy, Clone, Eq, Ord, Hash, Debug)] enum MaybeStaticStr<'a> { Static(&'static str), Borrowed(&'a str), @@ -793,6 +793,18 @@ impl<'a> MaybeStaticStr<'a> { } } +impl PartialEq for MaybeStaticStr<'_> { + fn eq(&self, other: &Self) -> bool { + self.get() == other.get() + } +} + +impl PartialOrd for MaybeStaticStr<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.get().cmp(other.get())) + } +} + /// The "payload" of a log message. /// /// # Use From cc89cc6e41190de36892e33fff48e5f48cf57fa9 Mon Sep 17 00:00:00 2001 From: Matteo Zeggiotti Date: Fri, 19 Jun 2026 12:44:16 +0200 Subject: [PATCH 3/4] Review: fixed other comparisons --- src/lib.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 442e169b2..d4c5dbdad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -777,7 +777,7 @@ impl LevelFilter { } } -#[derive(Copy, Clone, Eq, Ord, Hash, Debug)] +#[derive(Copy, Clone, Hash, Debug)] enum MaybeStaticStr<'a> { Static(&'static str), Borrowed(&'a str), @@ -793,15 +793,23 @@ impl<'a> MaybeStaticStr<'a> { } } +impl Eq for MaybeStaticStr<'_> {} + impl PartialEq for MaybeStaticStr<'_> { fn eq(&self, other: &Self) -> bool { self.get() == other.get() } } +impl Ord for MaybeStaticStr<'_> { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.get().cmp(other.get()) + } +} + impl PartialOrd for MaybeStaticStr<'_> { fn partial_cmp(&self, other: &Self) -> Option { - Some(self.get().cmp(other.get())) + Some(self.cmp(other)) } } From a9b57119a631249fc8e881c7ef78e2028aacb823 Mon Sep 17 00:00:00 2001 From: Matteo Zeggiotti Date: Fri, 19 Jun 2026 14:46:15 +0200 Subject: [PATCH 4/4] Review: fallback to the &str hash --- src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d4c5dbdad..9b5317a22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -777,7 +777,7 @@ impl LevelFilter { } } -#[derive(Copy, Clone, Hash, Debug)] +#[derive(Copy, Clone, Debug)] enum MaybeStaticStr<'a> { Static(&'static str), Borrowed(&'a str), @@ -813,6 +813,12 @@ impl PartialOrd for MaybeStaticStr<'_> { } } +impl std::hash::Hash for MaybeStaticStr<'_> { + fn hash(&self, state: &mut H) { + self.get().hash(state); + } +} + /// The "payload" of a log message. /// /// # Use