1

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(()) } 
1
  • 3
    Note that the result of the match is being bound to number. What could the type of number be? In your version, the result of the match could be either of type i32 or Result, and the type of number can only be one or the other, chosen at compile time. Commented Mar 20, 2022 at 3:01

2 Answers 2

5
 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.

Sign up to request clarification or add additional context in comments.

Comments

3

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)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.