Code only compiles with try!, not with question mark syntax

3146316
Opened by Felix Rath at 2021-05-16 19:46:23

The following code only compiles with try!, not when using the ?-syntax instead:

#![feature(question_mark)]

fn foo() -> Result<Vec<u32>, std::num::ParseIntError> {
    let s = &["42", "1337"];

    let parsed: Vec<u32> = try!(s.iter().map(|str| {
        let val = str.parse::<u32>()?;
        Ok(val + 1)
    }).collect());

    Ok(parsed)
}

fn main() {
    println!("{:?}", foo());
}

Replacing the single try! in function foo with its ? equivalent produces the following error:

error[E0284]: type annotations required: cannot resolve `<_ as std::ops::Carrier>::Success == _`
 --> <anon>:6:28
  |
6 |     let parsed: Vec<u32> = s.iter().map(|str| {
  |                            ^

error: aborting due to previous error

Example on playground: https://is.gd/CPUV0f (replace try! with ? to see the error)

Rustc version: rustc 1.13.0-nightly (acd3f796d 2016-08-28)

Note: @KiChjang mentioned on IRC that using turbofish on the collect call, .collect::<Result<_,_>>() , makes the ? version compile again.

  1. This is a known issue and has to to do with how the Carrier trait currently works. There's an old discussion at https://github.com/rust-lang/rust/pull/35056 which should be continued at https://github.com/rust-lang/rfcs/issues/1718.

    Steven Allen at 2016-09-04 14:47:01

  2. @Stebalien thanks! Wasn't aware of the already existing discussion.

    Felix Rath at 2016-09-04 15:13:25

  3. This compiles today; closing.

    Mark Rousskov at 2017-06-23 13:59:23

  4. I think this issue may need to be re-opened. I ran into it today (rustc 1.26.0-nightly (9cb18a92a 2018-03-02)). The example doesn't compile anymore without the type annotation.

    https://play.rust-lang.org/?gist=f12d5c5166d268479961bcbb2eccbd50&version=nightly

       Compiling playground v0.0.1 (file:///playground)
    error[E0284]: type annotations required: cannot resolve `<_ as std::ops::Try>::Ok == _`
     --> src/main.rs:6:28
      |
    6 |       let parsed: Vec<u32> = s.iter().map(|str| {
      |  ____________________________^
    7 | |         let val = str.parse::<u32>()?;
    8 | |         Ok(val + 1)
    9 | |     }).collect()?;
      | |_________________^
    
    error: aborting due to previous error
    

    compressed at 2018-03-11 21:32:51

  5. Current output for the last comment:

    error[E0284]: type annotations needed
     --> src/main.rs:9:8
      |
    9 |     }).collect()?;
      |        ^^^^^^^
      |        |
      |        cannot infer type
      |        help: consider specifying the type argument in the method call: `collect::<B>`
      |
      = note: cannot resolve `<_ as std::ops::Try>::Ok == _`
    

    It should work without annotations, but at least we lead people in the right direction :-/

    Esteban Kuber at 2020-01-17 03:50:36

  6. I think this issue may need to be re-opened. I ran into it today (rustc 1.26.0-nightly (9cb18a92a 2018-03-02)). The example doesn't compile anymore without the type annotation.

    https://play.rust-lang.org/?gist=f12d5c5166d268479961bcbb2eccbd50&version=nightly

    Current output of that link:

    error[E0283]: type annotations needed
     --> src/main.rs:9:8
      |
    9 |     }).collect()?;
      |        ^^^^^^^ cannot infer type
      |
      = note: cannot satisfy `_: Try`
      = note: required by `into_result`
    help: consider specifying the type argument in the method call
      |
    9 |     }).collect::<B>()?;
      |               ^^^^^
    

    Felix Rath at 2021-05-16 19:46:23