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

Quantity.sqrt() doesn't exist when defining a new system of quantities #100

Closed
Yoshanuikabundi opened this issue Aug 7, 2018 · 4 comments

Comments

@Yoshanuikabundi
Copy link

Hi again! This one might be me confused about configuration stuff but I can't get the Quantity.sqrt() method to work. Fortunately I can work around it. Example code:

//! Example showing how to create a custom system of quantities.

#[macro_use]
extern crate uom;

use length::{
    foot,
    meter
};
use area::meter2;

fn main() {
    let l1 = f32::Length::new::<meter>(10.0);

    println!(
        "{:?}",
        (l1 * l1)
    );

    // This works
    println!(
        "A square with side length {:?} {} has area {:?} {}",
        l1.get(foot),
        foot::abbreviation(),
        (l1 * l1).get(meter2),
        meter2::abbreviation()
    );

    let a1 = f32::Area::new::<meter2>(100.0);

    // This works, but obviously not ideal or safe
    println!(
        "A square with area {:?} {} has side length {:?} {}",
        a1.get(::meter2),
        meter2::abbreviation(),
        f32::Length::new::<meter>(a1.get(meter2).sqrt()).get(foot),
        foot::abbreviation()
    );

    // This doesn't work
    println!(
        "A square with area {:?} {} has side length {:?} {}",
        a1.get(::meter2),
        meter2::abbreviation(),
        a1.sqrt().get(foot),
        foot::abbreviation()
    );
}

#[macro_use]
mod length {
    quantity! {
        /// Length (base unit meter, m<sup>1</sup>).
        quantity: Length; "length";
        /// Length dimension, m<sup>1</sup>.
        dimension: Q<P1>; // length
        units {
            @meter: 1.0E0; "m", "meter", "meters";
            @foot: 3.048E-1; "ft", "foot", "feet";
        }
    }
}

#[macro_use]
mod area {
    quantity! {
        /// Area (base unit square meter, m<sup>2</sup>).
        quantity: Area; "area";
        /// Area dimension, m<sup>2</sup>.
        dimension: Q<P2>; // length
        units {
            @meter2: 1.0E0; "m^2", "square meter", "square meters";
        }
    }
}

system! {
    quantities: Q {
        length: meter, L;
    }

    units: U {
        mod length::Length,
        mod area::Area,
    }
}

mod s {
    pub use *;
}

storage_types! {
    pub types: Float;

    Q!(s, V);
}

And the compiler error:

% cargo run 
   Compiling uomtest v0.1.0 (file:///home/yoshanuikabundi/projects/uomtest)
error[E0599]: no method named `sqrt` found for type `Quantity<Dimension<L=uom::typenum::PInt<uom::typenum::UInt<uom::typenum::UInt<uom::typenum::UTerm, uom::typenum::B1>, uom::typenum::B0>>>, Units<f32, length=length::meter>, f32>` in the current scope
  --> src/main.rs:34:12
   |
34 |           a1.sqrt().get(::foot),
   |              ^^^^
...
66 | / system! {
67 | |     quantities: Q {
68 | |         length: meter, L;
69 | |     }
...  |
74 | |     }
75 | | }
   | |_- method `sqrt` not found for this
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following traits define an item `sqrt`, perhaps you need to implement one of them:
           candidate #1: `uom::num::Float`
           candidate #2: `uom::num_traits::real::Real`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: Could not compile `uomtest`.

To learn more, run the command again with --verbose.

I believe the Area quantity should have the sqrt method. If I compile the docs and search for "sqrt", it only shows up in the uom crate. I'm using uom from the dev-test-fix branch, but it happens with 0.19.0 as well, and I'm on Rust 1.28.0. Thanks again!

@iliekturtles
Copy link
Owner

  1. Did you compile uom with the std feature, sqrt requires it: https://github.com/iliekturtles/uom/blob/master/src/system.rs#L749
  2. Try use uom::num::Float;:
       = help: items from traits can only be used if the trait is implemented and in scope
       = note: the following traits define an item `sqrt`, perhaps you need to implement one of them:
               candidate #1: `uom::num::Float`
    

@Yoshanuikabundi
Copy link
Author

  1. I tried with the default features which I understand includes the std feature, and I've tried again first with every feature and then with only the f32 and std features. Same result every time.

  2. I shoulda tried that! Unfortunately it doesn't fix the problem. I also tried bringing the PartialDiv trait into scope just in case, which is in sqrt's trait bounds, but no joy. I've copied both imports into all the modules in the test to make sure I caught the right macro. Still won't compile.

@iliekturtles
Copy link
Owner

Ahhh! I was able to reproduce. The issue is that the #[cfg(feature = "std")] gets injected into your crate and isn't being controlled by the uom crate's features. As a short-term work-around you can add a std` feature to your crate.

There was a similar issue with the storage_types! macro so I have an idea about how to resolve the issue.

iliekturtles added a commit that referenced this issue Aug 29, 2018
Add macros to condtionally include contents based on features `uom` was
compiled with rather then features in the destination crate. Resolves
#98 and #100.
@iliekturtles
Copy link
Owner

Closing this issue. Just realized that it was resolved by 73075f4 but Github's commit message parsing didn't automatically close the issue.

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