NREL / routee-compass

The RouteE-Compass energy-aware routing engine
https://nrel.github.io/routee-compass/
BSD 3-Clause "New" or "Revised" License
9 stars 4 forks source link

OrderedFloat does not implement Mul #197

Open robfitzgerald opened 2 months ago

robfitzgerald commented 2 months ago

While deriving derive_more numeric traits for Cost (or other types that wrap OrderedFloat) compiles, when we attempt to use the methods, we get a failure:

let x = Cost::ZERO * Cost::ONE;
cannot multiply `ordered_float::OrderedFloat<f64>` by `model::unit::cost::Cost`
the trait `std::ops::Mul<model::unit::cost::Cost>` is not implemented for `ordered_float::OrderedFloat<f64>`
the following other types implement trait `std::ops::Mul<Rhs>`:
  <ordered_float::OrderedFloat<T> as std::ops::Mul>
  <ordered_float::OrderedFloat<T> as std::ops::Mul<T>>
  <ordered_float::OrderedFloat<T> as std::ops::Mul<&'a T>>
  <ordered_float::OrderedFloat<T> as std::ops::Mul<&'a ordered_float::OrderedFloat<T>>>
  <&'a ordered_float::OrderedFloat<T> as std::ops::Mul<ordered_float::OrderedFloat<T>>>
  <&'a ordered_float::OrderedFloat<T> as std::ops::Mul<T>>
  <&'a ordered_float::OrderedFloat<T> as std::ops::Mul<&'a T>>
1 redundant requirement hidden
required for `model::unit::cost::Cost` to implement `std::ops::Mul`
kylecarow commented 1 month ago

@nreinicke This issue seems to be relevant: https://github.com/JelteF/derive_more/issues/168

Adding #[mul(forward)] to InternalFloat creates an impl for e.g. InternalFloat::ZERO * InternalFloat::ONE;, but does not generate an impl for InternalFloat::ZERO * 1.0; removing that attribute does the opposite.

Until that issue is resolved, it seems like we either keep it as is, or, as the compiler suggests, add .into() calls wherever we have internal floats multiplied by primitive floats (gross):

error[E0308]: mismatched types
  --> routee-compass-core/src/model/unit/weight_unit.rs:24:44
   |
24 |             (S::Kg, S::Pounds) => *value * 2.20462,
   |                                            ^^^^^^^ expected `InternalFloat`, found floating-point number
   |
help: call `Into::into` on this expression to convert `{float}` into `unit::internal_float::InternalFloat`
   |
24 |             (S::Kg, S::Pounds) => *value * 2.20462.into(),
   |                                                   +++++++

Leaving this here for now, but it should still be possible to get the contained primitive float out of one of the objects and use that, i.e. by sequential .0 accesses