Open XMPPwocky opened 9 years ago
I encountered a similar problem:
fn sqrt2() -> f64 {
let x = 2.0;
x.sqrt()
}
fn two_plus_three() -> u64 {
let x = 2;
x.checked_add(3).unwrap()
}
In both cases, the compiler fails to infer the type of x
even though it has enough information to do so (from the return value of the functions).
Moreover, the language reference says that
If the program context under-constrains the type, it defaults to f64.
So, if the reference was respected, it would default to f64
and call the right method.
I just ran into this writing some example codes (where it's more likely to have a lot of 'unconstrained' hard coded constants), note the very unhelpful error message:
fn main() {
let _ = 0.5.sqrt();
}
error: no method named `sqrt` found for type `{float}` in the current scope
--> src/main.rs:2:21
|
2 | let _ = 0.5.sqrt();
| ^^^^
|
= help: items from traits can only be used if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
= help: candidate #1: `use rand::FloatMath;`
error: aborting due to previous error
error: Could not compile `playground`.
To learn more, run the command again with --verbose.
https://play.rust-lang.org/?gist=24e7667d5a1ea0c7b8702e9ac4a075b4&version=stable
This was also reported as a pain point in the "Ideas for making Rust easier for beginners" internals thread: https://internals.rust-lang.org/t/ideas-for-making-rust-easier-for-beginners/4761/37
Readers of our book 'Programming Rust' have reported errata related to this, because it's hard to explain that operators and trait methods work on unresolved {float}
values, but associated functions don't.
The current error is much clearer, but this ticket is still valid because it is about inference itself:
error[E0689]: can't call method `sqrt` on ambiguous numeric type `{float}`
--> src/main.rs:2:17
|
2 | let _ = 0.5.sqrt();
| ^^^^
|
help: you must specify a concrete type for this numeric value, like `f32`
|
2 | let _ = 0.5_f32.sqrt();
| ~~~~~~~
Weirdly enough, this does work for trait methods (playground):
trait Foo {
fn foo(&self);
}
impl Foo for i16 {
fn foo(&self) {
println!("i16");
}
}
// Uncomment to change the output in `main`
//
// impl Foo for i32 {
// fn foo(&self) {
// println!("i32");
// }
// }
fn main() {
3.foo();
}
So it definitely seems like it should be possible.
I would expect
2.0.sqrt()
to return sqrt(2) as a f64. Instead,... and the Float trait is deprecated!
This also occurs with integer literals.
I ran into this in the wild while doing an exponential decay:
A workaround is to annotate the literal's type explicitly.