user480184
user480184

Reputation:

Rust Type Inference for Result

I am new to Rust while going through the documentation for Iterator Trait and running some code I found a strange code behaviour. I am trying to find some documentation that could explain that (described below). Could someone please explain or point me to an explanation ?

Problem statement:

When I create a single variable like shown below

let testvariable = Ok(1);

I get the error below

let testvariable = Ok(1);
    ------------   ^^ cannot infer type for type parameter `E` declared on the enum `Result`
    |
    consider giving `testvariable` the explicit type `std::result::Result<i32, E>`, where the type parameter `E` is specified

However, when I create an array as below

let results = [Ok(1), Ok(3)];

There is no error. Somehow Rust has inferred the type of the array to be [std::result::Result<i32, &str>; 2]

Edit: Posting code for viewers to try out

fn main() {
    let testvariable = Ok(1);
    let results = [Ok(1), Ok(3)];
    let result: Result<Vec<_>, &str> = results.iter().cloned().collect();
}

Edit: Rearranged the order of questions to provide clarity on the inquiry. As I show below, its somewhat clear why &str makes it in the full type of the results array. What is not clear is why it does not make it to the type of the testvariable.

What I am trying to understand is the following:

  1. Why does the second case work, while the first case throws an error ?
  2. How is the type E inferred to be &str in the second case ?

Based on my digging around (see below) I could (somewhat) understand how/why the &str type is coming into picture but couldn't explain the difference.

Below I describe some of my efforts to figure this out:

This seems to be an expected behaviour as shown in the last example here (the type of the results variable should match the above mentioned type).

The closest I could get to figuring this out - was the implementation of the ok method on the Result enum here where it assigns the type &str to E in the example below.

/// let x: Result<u32, &str> = Ok(2);

Post this I am assuming that somehow the variant value of Result::None is being automatically being converted to &str but I couldn't find it. Moreover, the comments on the enum keyword in source didn't provide much clues.

Upvotes: 1

Views: 1537

Answers (2)

user480184
user480184

Reputation:

Thanks all who answered.

My newbie brain took some time before it understood the answer so I am posting a detailed response to this.

Line 1:    fn main() {
Line 2:        let testvariable = Ok(1);
Line 3:        let results = [Ok(1), Ok(3)];
Line 4:        let result: Result<Vec<_>, &str> = results.iter().cloned().collect();
Line 5:    }

Why Line 2 throws an error and Line 3 still works is because the compiler can infer the type of results from usage of results variable in Line 4.

I was under the impression that the code that is used for type inference would include only the statement where a variable is defined and beyond that, use the inferred type everywhere else.

In fact, if we remove the line 4 and try the code snippet below, although the code compiles, the type of results variable changes to error proving that the type of results variable is being inferred due to line 4.

Line 1:    fn main() {
Line 2:        let testvariable = Ok(1);
Line 3:        let results = [Ok(1), Ok(3)];
Line 4:        //let result: Result<Vec<_>, &str> = results.iter().cloned().collect();
Line 5:    }

Upvotes: 0

Jmb
Jmb

Reputation: 23244

I assume that your array version is actually this example from the docs:

let results = [Ok(1), Ok(3)];

let result: Result<Vec<_>, &str> = results.iter().cloned().collect();

// gives us the list of answers
assert_eq!(Ok(vec![1, 3]), result);

The compiler is able to infer that the type for Result::Err is the same for the results array and the result variable. Since the latter is specified to be &str, the compiler also uses it for the array.

For your single variable case, if you never use the error variant then the compiler has no way of knowing what it is and complains.

Upvotes: 2

Related Questions