Skip to content

Understanding type errors #134

@dmit

Description

@dmit

Uom does a great job of disallowing illegal operations on incompatible units, but currently the compile-time errors produced are not very straightforward.

A basic example:

use uom::si::f64::*;
use uom::si::{length, mass};

fn main() {
    let len = Length::new::<length::meter>(1.0);
    let mass = Mass::new::<mass::kilogram>(1.0);
    let sum = len + mass;
    println!("{:?}", sum);
}

results in the following compiler output:

error[E0308]: mismatched types
 --> src\main.rs:7:21
  |
7 |     let sum = len + mass;
  |                     ^^^^ expected struct `typenum::int::PInt`, found struct `typenum::int::Z0`
  |
  = note: expected type `uom::si::Quantity<dyn uom::si::Dimension<L = typenum::int::PInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>>, T = typenum::int::Z0, N = typenum::int::Z0, Th = typenum::int::Z0, M = typenum::int::Z0, J = typenum::int::Z0, I = typenum::int::Z0, Kind = dyn uom::Kind>, dyn uom::si::Units<f64, electric_current = uom::si::electric_current::ampere, amount_of_substance = uom::si::amount_of_substance::mole, thermodynamic_temperature = uom::si::thermodynamic_temperature::kelvin, luminous_intensity = uom::si::luminous_intensity::candela, length = uom::si::length::meter, time = uom::si::time::second, mass = uom::si::mass::kilogram>, _>`
             found type `uom::si::Quantity<dyn uom::si::Dimension<L = typenum::int::Z0, T = typenum::int::Z0, N = typenum::int::Z0, Th = typenum::int::Z0, M = typenum::int::PInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>>, J = typenum::int::Z0, I = typenum::int::Z0, Kind = dyn uom::Kind>, dyn uom::si::Units<f64, electric_current = uom::si::electric_current::ampere, amount_of_substance = uom::si::amount_of_substance::mole, thermodynamic_temperature = uom::si::thermodynamic_temperature::kelvin, luminous_intensity = uom::si::luminous_intensity::candela, length = uom::si::length::meter, time = uom::si::time::second, mass = uom::si::mass::kilogram>, _>`

Are there known ways to improve the debugging process in this situation? My current approach is to figure out which two variables are involved, what their respective units are, and why the operation on those units doesn't make sense.

There are open rustc issues like rust-lang/rust#50310 that would turn

Dimension<L = typenum::int::PInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>>, ...

into

Dimension<L = P1, ...

which is a solid readability improvement, but doesn't really help me see what the logical error in the code is. Is it possible to do better with what we have in the compiler now? Any tips and tricks are greatly appreciated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions