Reputation: 517
fn some_fn(a:f32 , b: f32) -> Result<f32, &'static str> {
if b == 0.0 {
return Err("Error for some reason");
}
Ok(a / b)
}
This function compiles, but when I remove the return statement (just for fun)
fn some_fn(a:f32 , b: f32) -> Result<f32, &'static str> {
if b == 0.0 {
Err("Error for some reason");
}
Ok(a / b)
}
It gives the error:
error[E0282]: type annotations needed
--> main.rs:3:9
|
3 | Err("Error for some reason");
| ^^^ cannot infer type of the type parameter `T` declared on the enum `Result`
|
help: consider specifying the generic arguments
|
3 | Err::<T, &str>("Error for some reason");
| +++++++++++
What is going on here? Because I removed the return statement, I would expect it to say "Expected Result<> found something else". What's wrong with the type inference? And the suggestion? I know I should get an error but I am confused by this one.
Upvotes: 1
Views: 1096
Reputation: 22601
That's because the Err
ends up nowhere. It just gets discarded right away, and either way the Ok
gets executed and returned.
Because the Err
value never gets returned or combined with an Ok
value, Rust doesn't know what its Ok
value type should be. And Rust always has to know exactly what type a variable is, even if only one part of the enum gets used.
You probably intended to write:
fn some_fn(a:f32 , b: f32) -> Result<f32, &'static str> {
if b == 0.0 {
Err("Error for some reason")
} else {
Ok(a / b)
}
}
I would expect it to say "Expected Result<> found something else"
That would only happen if you actually did something with the Err
value. But the way you wrote it, it will just silently be discarded. You don't store it anywhere or do something with it.
Also, Err
still is a Result<>
type. So if anything, it would say "Expected something else, got Result<>". But I'm unsure where it would expect anything in your code, the only place it expects a Result
is in the return value, and as you just deleted the return
, the only thing returned is the Ok
value, which indeed is a Result<>
as expected.
So if you just specify the value type of your Err
, it compiles fine:
fn some_fn(a: f32, b: f32) -> Result<f32, &'static str> {
if b == 0.0 {
Err::<(), _>("Error for some reason");
}
Ok(a / b)
}
Although it now gives you, as expected, the warning that the Err
value never gets used:
warning: unused `Result` that must be used
--> src/lib.rs:3:9
|
3 | Err::<(), _>("Error for some reason");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_must_use)]` on by default
= note: this `Result` may be an `Err` variant, which should be handled
Upvotes: 1