Why does the compiler infer the type here to be the unit type?

The following happens on current beta. In the below example, the type of msg is inferred by the compiler to be the unit type. This seems unusual because I would expect the compiler to error saying it cannot infer type. What is the reason that this happens? Is this the expected behaviour?

use std::io::{Result, ErrorKind};
use async_std::task;
use serde::de::DeserializeOwned;

async fn parse<T: DeserializeOwned>(s: String) -> Result<T> {
    Ok(serde_json::from_str(&s).map_err(|_| ErrorKind::InvalidData)?)
}

async fn body_json(s: String) -> Result<String> {
    let msg = parse(s).await?;
    println!("parsed: {:?}", msg);
    Ok(serde_json::to_string(&msg).map_err(|_| ErrorKind::InvalidData)?)
}

fn main() {
    // works because it can be deserialized into unit
    task::block_on(body_json("null".to_string())).unwrap();

    // fails because can't be deserialized into unit 
    task::block_on(body_json("{}".to_string())).unwrap();
}

If I just change

    let msg = parse(s).await?;

to

    let msg = parse(s).await.unwrap();

Then it fails with

error[E0698]: type inside `async` object must be known in this context
  --> src/main.rs:10:15
   |
10 |     let msg = parse(s).await.unwrap();
   |               ^^^^^ cannot infer type for `T`
   |
note: the type is part of the `async` object because of this `await`
  --> src/main.rs:10:15
   |
10 |     let msg = parse(s).await.unwrap();
   |               ^^^^^^^^^^^^^^

Originally encountered here.

Resolved with

This has to do with the ! type and how it defaults to () if no other types are involved.

2 Likes