Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subtracting thermodynamic temperatures should produce a temperature interval #380

Open
ryanolf-tb opened this issue Oct 7, 2022 · 5 comments

Comments

@ryanolf-tb
Copy link

I have an application where I need to take a difference of thermodynamic temperatures, and my expectation would be that this produces a temperature interval. At present, this operation is not allowed.

@iliekturtles
Copy link
Owner

An additional Sub impl should be added and it looked trivial so I tried and get the following error. TLDR: without specialization the default Sub impl conflicts with the desired impl and there isn't a way to add a negative bound to the new impl that is the opposite of D::Kind: $crate::marker::$AddSubTrait,.

I'll keep thinking on ways to work around the issue without specialization.

   Compiling uom v0.33.0 (/home/mjboutin/uom)
error[E0119]: conflicting implementations of trait `std::ops::Sub<si::Quantity<(dyn si::Dimension<M = typenum::Z0, Kind = (dyn si::marker::TemperatureKind + 'static), N = typenum::Z0, L = typenum::Z0, I = typenum::Z0, T = typenum::Z0, J = typenum::Z0, Th = typenum::PInt<typenum::UInt<typenum::UTerm, typenum::B1>>> + 'static), _, _>>` for type `si::Quantity<(dyn si::Dimension<M = typenum::Z0, Kind = (dyn si::marker::TemperatureKind + 'static), N = typenum::Z0, L = typenum::Z0, I = typenum::Z0, T = typenum::Z0, J = typenum::Z0, Th = typenum::PInt<typenum::UInt<typenum::UTerm, typenum::B1>>> + 'static), _, _>`
   --> src/system.rs:395:17
    |
395 | /                 impl<D, Ul, Ur, V> $crate::lib::ops::$AddSubTrait<Quantity<D, Ur, V>>
396 | |                     for Quantity<D, Ul, V>
397 | |                 where
398 | |                     D: Dimension + ?Sized,
...   |
413 | |                     }
414 | |                 }}
    | |_________________^ conflicting implementation for `si::Quantity<(dyn si::Dimension<M = typenum::Z0, Kind = (dyn si::marker::TemperatureKind + 'static), N = typenum::Z0, L = typenum::Z0, I = typenum::Z0, T = typenum::Z0, J = typenum::Z0, Th = typenum::PInt<typenum::UInt<typenum::UTerm, typenum::B1>>> + 'static), _, _>`
    |
   ::: src/si/thermodynamic_temperature.rs:177:1
    |
177 | / impl<Ul, Ur, V> crate::lib::ops::Sub<ThermodynamicTemperature<Ur, V>>
178 | |     for ThermodynamicTemperature<Ul, V>
179 | | where
180 | |     Ul: super::Units<V> + ?Sized,
...   |
193 | |     }
194 | | }
    | |_- first implementation here
    |
   ::: src/si/mod.rs:10:1
    |
10  | / system! {
11  | |     /// [International System of Quantities](https://jcgm.bipm.org/vim/en/1.6.html) (ISQ).
12  | |     ///
13  | |     /// ## Generic Parameters
...   |
112 | |     }
113 | | }
    | |_- in this macro invocation
    |
    = note: this error originates in the macro `impl_ops` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0119`.
error: could not compile `uom` due to previous error

@ryanolf-tb
Copy link
Author

I'm a bit confused about how the default Sub impl conflicts when it seems the compiler doesn't have an implementation for Sub for thermodynamic temperatures.

@iliekturtles
Copy link
Owner

The error in my previous comment was from an attempt to add a new Sub impl for ThermodynamicTemperature - TemperatureInterval. This new impl conflicts with the default Sub impl.

uom/src/system.rs

Lines 395 to 414 in 974449f

impl<D, Ul, Ur, V> $crate::lib::ops::$AddSubTrait<Quantity<D, Ur, V>>
for Quantity<D, Ul, V>
where
D: Dimension + ?Sized,
D::Kind: $crate::marker::$AddSubTrait,
Ul: Units<V> + ?Sized,
Ur: Units<V> + ?Sized,
V: $crate::num::Num + $crate::Conversion<V>,
{
type Output = Quantity<D, Ul, V>;
#[inline(always)]
fn $addsub_fun(self, rhs: Quantity<D, Ur, V>) -> Self::Output {
Quantity {
dimension: $crate::lib::marker::PhantomData,
units: $crate::lib::marker::PhantomData,
value: self.value $addsub_op change_base::<D, Ul, Ur, V>(&rhs.value),
}
}
}}

@ryanolf-tb
Copy link
Author

Why doesn't the default Sub impl work? There is some Rust subtlety here that I'm not seeing. Sorry! It seems odd that there's a conflicting implementation but that the compiler can't actually use that implementation for the operation on the given types.

@iliekturtles
Copy link
Owner

The default impl is for any Quantity - Quantity where the quantity's dimension's kind supports add/sub (line 399). ThermodynamicTemperature and TemperatureInterval are just type aliases for Quantity so they are covered by this default impl. However, because ThermodynamicTemperature's kind does not support add/sub the default impl does not take effect. A new specialized impl can't be added because the type aliases boil down to the same types in the default impl. If there was some way to add a negative trait bound then this could be used to make the two disjoint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants