Skip to content
Merged
Show file tree
Hide file tree
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## unreleased

### Fixed

- Fix `PartialEq` and `Ord` implementations. ([PR #36](https://github.com/teloxide/dptree/pull/36))
- For `Type` they were inconsistent and are replaced by the standard derived implementations.
- Adding a length check when checking equality of `DependencyMap`.

## 0.5.0 - 2025-06-19

### Added
Expand Down
16 changes: 15 additions & 1 deletion src/di.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl PartialEq for DependencyMap {
fn eq(&self, other: &Self) -> bool {
let keys1 = self.map.keys();
let keys2 = other.map.keys();
keys1.zip(keys2).map(|(k1, k2)| k1 == k2).all(|x| x)
keys1.len() == keys2.len() && keys1.zip(keys2).map(|(k1, k2)| k1 == k2).all(|x| x)
}
}

Expand Down Expand Up @@ -326,4 +326,18 @@ mod tests {
assert_eq!(map.try_get(), Some(Arc::new(42i32)));
assert_eq!(map.try_get::<f32>(), None);
}

#[test]
fn same_keys() {
let mut map_bool1 = DependencyMap::new();
let mut map_bool2 = DependencyMap::new();
let map_empty = DependencyMap::new();

map_bool1.insert(false);
map_bool2.insert(true);

assert_eq!(map_bool1, map_bool2);
assert_ne!(map_bool1, map_empty);
assert_ne!(map_bool2, map_empty);
}
}
64 changes: 35 additions & 29 deletions src/handler/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::{description, prelude::DependencyMap, HandlerDescription};

use std::{
any::TypeId,
cmp::Ordering,
collections::{BTreeMap, BTreeSet},
fmt::Write,
future::Future,
Expand Down Expand Up @@ -102,14 +101,16 @@ pub enum HandlerSignature {
/// A run-time representation of a type. Used only for run-time type inference
/// and checking of handler chains.
///
/// Type name field placed before type identifier field so that the derived Ord
/// implementation sorts types alphabetically.
/// See [`crate::type_check`].
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Type {
/// The unique type identifier.
pub id: TypeId,

/// The type name used for printing.
pub name: &'static str,

/// The unique type identifier.
pub id: TypeId,
}

impl Hash for Type {
Expand All @@ -119,29 +120,6 @@ impl Hash for Type {
}
}

impl PartialEq for Type {
/// Equality is done by type identifiers (type names are ignored).
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}

impl Eq for Type {}

impl PartialOrd for Type {
/// The partial order is done by type names for better diagnostics.
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Type {
/// The total order is done by type names for better diagnostics.
fn cmp(&self, other: &Self) -> Ordering {
self.name.cmp(other.name)
}
}

type DynFn<'a, Output> =
dyn Fn(DependencyMap, Cont<'a, Output>) -> HandlerResult<'a, Output> + Send + Sync + 'a;

Expand Down Expand Up @@ -679,7 +657,7 @@ mod tests {
handler::{endpoint, filter, filter_async},
};

use std::{collections::HashSet, iter::FromIterator};
use std::{any::Any, collections::HashSet, iter::FromIterator};

use maplit::{btreemap, btreeset, hashset};

Expand Down Expand Up @@ -1018,6 +996,34 @@ Make sure all the required values are provided to the handler. For more informat
);
}

#[test]
fn type_eq_ord_consistent() {
#[derive(Clone)]
struct A;

let ta1 = Type { id: A.type_id(), name: "A1" };
let ta2 = Type { id: A.type_id(), name: "A2" };

assert!(!(ta1 == ta2));
assert!(ta1 < ta2);
assert!(!(ta1 > ta2));
}

#[test]
fn type_btreeset_not_contains_duplicate_name() {
#[derive(Clone)]
struct A;
#[derive(Clone)]
struct B;

let ta = Type { id: A.type_id(), name: "DuplicateName" };
let tb = Type { id: B.type_id(), name: "DuplicateName" };
let set = btreeset! {ta};

assert!(ta != tb);
assert!(!set.contains(&tb));
}

#[tokio::test]
async fn type_infer_check_chained_combinators() {
#[derive(Clone)]
Expand Down