Reputation: 707
I am reading Rust by Example book. In this example removing return
in Err(e) => return Err(e)
causes an error: expected `i32`, found enum `Result``
. Why is that?
What is the difference between Err(e) => return Err(e)
and Err(e) => Err(e)
?
Here is the code from the example:
use std::num::ParseIntError;
fn main() -> Result<(), ParseIntError> {
let number_str = "10";
let number = match number_str.parse::<i32>() {
Ok(number) => number,
Err(e) => return Err(e),
};
println!("{}", number);
Ok(())
}
Upvotes: 1
Views: 2562
Reputation: 10196
All arms of a match
have to have "compatible" types. This either mean they all have the same type:
fn is_some<T>(opt: &Option<T>) -> bool {
match opt {
// both arms have type bool
Some(_) => true,
None => false,
}
}
or some of the branches need to direct control flow away from the match in some way.
The main rule to keep in your head is that every variable in Rust needs a single type (ignoring variance w.r.t. lifetimes). In your case, if you didn't have the return
keyword, what would be the type of number
?
If the parse succeeds, number
would be an i32
. If it fails, it would be an Err(ParseIntError)
. This isn't allowed, so you get a compile error.
However, if you return Err(e)
, number
will always be an i32
(since return
prevents the rest of the function running, so number
doesn't need a type).
A similar thing applies to other control-flow keywords (e.g. continue
, break
, ...), as well as things that are guaranteed to not return, like panic!()
(look up the Never
/!
type for more info)
Upvotes: 3
Reputation: 165386
let number = match number_str.parse::<i32>() {
Ok(number) => number,
Err(e) => return Err(e),
};
This says if number_str.parse::<i32>()
returns an Ok
to set number
to number
, an i32. If it returns an Err
to immediately return Err(e)
, which is a Result
, from main
, number
is not set.
That's fine because number
can only be an i32
and main
does return a Result
.
let number = match number_str.parse::<i32>() {
Ok(number) => number,
Err(e) => Err(e),
};
This says if number_str.parse::<i32>()
returns an Ok
to set number
to number
, an i32, same as before. If it returns an Err
to set number
to Err(e)
, which is a Result
.
number
cannot be both an i32
and a Result
, so you get a compiler error.
Upvotes: 5