From c99dffd011b259140baaefaf105f21a67bfafdc1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 11:30:37 +0000 Subject: [PATCH 1/2] Initial plan From b4425502b90b6ebc54c7134d9804ce973fb61297 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 11:39:53 +0000 Subject: [PATCH 2/2] Fix broken Eq/Ord semantics for AssetCapacity by implementing PartialEq via total_cmp Co-authored-by: alexdewar <23149834+alexdewar@users.noreply.github.com> --- docs/release_notes/upcoming.md | 3 +++ src/asset/capacity.rs | 45 +++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/docs/release_notes/upcoming.md b/docs/release_notes/upcoming.md index 6d94973c4..3bb071243 100644 --- a/docs/release_notes/upcoming.md +++ b/docs/release_notes/upcoming.md @@ -54,6 +54,8 @@ ready to be released, carry out the following steps: - Users can now set demand to zero in `demand.csv` ([#871]) - Fix: sign for levies of type `net` was wrong for inputs ([#969]) - Fix `--overwrite` option for `save-graphs` command ([#1001]) +- Fix broken `Eq`/`Ord` consistency for `AssetCapacity`: equality is now aligned with + `total_cmp` ordering ([#1158]) [#767]: https://github.com/EnergySystemsModellingLab/MUSE2/pull/767 [#868]: https://github.com/EnergySystemsModellingLab/MUSE2/pull/868 @@ -72,3 +74,4 @@ ready to be released, carry out the following steps: [#1021]: https://github.com/EnergySystemsModellingLab/MUSE2/pull/1021 [#1022]: https://github.com/EnergySystemsModellingLab/MUSE2/pull/1022 [#1030]: https://github.com/EnergySystemsModellingLab/MUSE2/pull/1030 +[#1158]: https://github.com/EnergySystemsModellingLab/MUSE2/pull/1158 diff --git a/src/asset/capacity.rs b/src/asset/capacity.rs index d0ae3127c..3e1382969 100644 --- a/src/asset/capacity.rs +++ b/src/asset/capacity.rs @@ -4,7 +4,7 @@ use std::cmp::Ordering; use std::ops::{Add, Sub}; /// Capacity of an asset, which may be continuous or a discrete number of indivisible units -#[derive(Clone, PartialEq, Copy, Debug)] +#[derive(Clone, Copy, Debug)] pub enum AssetCapacity { /// Continuous capacity Continuous(Capacity), @@ -13,6 +13,12 @@ pub enum AssetCapacity { Discrete(u32, Capacity), } +impl PartialEq for AssetCapacity { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + impl Add for AssetCapacity { type Output = Self; @@ -213,4 +219,41 @@ mod tests { let got = orig.apply_limit_factor(factor); assert_eq!(got, AssetCapacity::Discrete(expected_units, unit_size)); } + + /// `PartialEq` must be consistent with `Ord`: two values are equal iff `cmp` returns + /// `Ordering::Equal`. + #[rstest] + #[case::continuous_equal( + AssetCapacity::Continuous(Capacity(1.0)), + AssetCapacity::Continuous(Capacity(1.0)), + true + )] + #[case::continuous_positive_zero_vs_negative_zero( + AssetCapacity::Continuous(Capacity(0.0)), + AssetCapacity::Continuous(Capacity(-0.0)), + false + )] + #[case::continuous_unequal( + AssetCapacity::Continuous(Capacity(1.0)), + AssetCapacity::Continuous(Capacity(2.0)), + false + )] + #[case::discrete_equal( + AssetCapacity::Discrete(3, Capacity(4.0)), + AssetCapacity::Discrete(3, Capacity(4.0)), + true + )] + #[case::discrete_unequal( + AssetCapacity::Discrete(2, Capacity(4.0)), + AssetCapacity::Discrete(3, Capacity(4.0)), + false + )] + fn eq_consistent_with_ord( + #[case] a: AssetCapacity, + #[case] b: AssetCapacity, + #[case] expected_eq: bool, + ) { + assert_eq!(a == b, expected_eq); + assert_eq!(a.cmp(&b) == Ordering::Equal, expected_eq); + } }