1

I was playing around with try blocks but I can't figure out how to make this code work (Playground):

#![feature(try_blocks)]

fn get_val(vec: Vec<i32>) -> Result<i32, String> {
    let (v1, v2) =
        try { (vec.get(0)?, vec.get(1)?) }.ok_or("failed to collect elements".to_string())?;

    if v1 < v2 {
        return Err("condition failed".to_string());
    }
    Ok(v1 + v2)
}
error[E0282]: type annotations needed
 --> src/lib.rs:5:9
  |
5 |         try { (vec.get(0)?, vec.get(1)?) }.ok_or("failed to collect elements".to_string())?;
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
  |
  = note: type must be known at this point
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Midnight Exigent
  • 615
  • 4
  • 15
  • See also [How do I fix the error “type annotations needed” when creating a closure that uses the try operator?](https://stackoverflow.com/q/51476828/155423) – Shepmaster May 17 '21 at 17:51
  • It's hard to answer multiple questions made in one post, so I've removed the unrelated question. Please separate them into multiple questions so that we can help you better and so that your questions will help others in the future that have one of the same questions as you! – Shepmaster May 17 '21 at 17:52

1 Answers1

2

Rust can't infer the type of your try block. Your sample code looks like

let (v1, v2) =
    try { (vec.get(0)?, vec.get(1)?) }.ok_or("failed to collect elements".to_string())?;

In Rust, ? (and by extension the try { ... } nightly feature) can return a value of any type which implements the Try trait. Now, it's obvious to a human reader that you want Option<(&i32, &i32)>, but to the computer, you could also want some other type. Specifically, any type which implements Try and has an ok_or method would suffice.

You can make the code work with an explicit type signature

let tmp: Option<(&i32, &i32)> = try { (vec.get(0)?, vec.get(1)?) };
let (v1, v2) =
    tmp.ok_or("failed to collect elements".to_string())?;
Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116