Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error "cannot infer type" when using '?' in async block + bad diagnostic #63502

Open
russelltg opened this issue Aug 12, 2019 · 9 comments
Open

Error "cannot infer type" when using '?' in async block + bad diagnostic #63502

russelltg opened this issue Aug 12, 2019 · 9 comments

Comments

@russelltg
Copy link

@russelltg russelltg commented Aug 12, 2019

This seems related to #42424, except I don't see an obvious workaround like in #42424.

#![feature(async_await)]

use std::io::Error;

fn make_unit() -> Result<(), Error> { 
    Ok(())
}

fn main() {
    let fut = async {
        make_unit()?;
        
        Ok(())
    };
}

Fails with the error

error[E0282]: type annotations needed for `impl std::future::Future`
  --> src/main.rs:11:9
   |
10 |     let fut = async {
   |         --- consider giving `fut` the explicit type `impl std::future::Future`, with the type parameters specified
11 |         make_unit()?;
   |         ^^^^^^^^^^^^ cannot infer type

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=ea7e5f7b6e1637f6a39aee0b8209c99e

First of all, it seems like this shouldn't be an error--it should be able to deduce that the return type is Result<(), io::Error>, but also the diagnostic does not work. If you try to add impl std::future::Future<Output=Result<(), Error>> as a type annotation, it also fails to compile because impl Trait is only allowed as return types and argument types.

@estebank
Copy link
Contributor

@estebank estebank commented Aug 12, 2019

Opened #63504 for the incorrect suggestion. For the main issue, ? interacts in non-obvious ways with type inference because it does implicit conversion. In this case, because fut doesn't explicitly constraint what the expected type is, rustc doesn't know what Result<(), std::io:Error> should be converted to.

There are other similar tickets filed about these kind of type inference issues: #49391, #38508, #46333, #46680, #48089, #61152, #58517 and #63082.

(larger work around ? tracked in #31436)

Loading

@cramertj
Copy link
Member

@cramertj cramertj commented Aug 13, 2019

I don't see an obvious workaround

The workaround is this:

use std::io::Error;

fn make_unit() -> Result<(), Error> { 
    Ok(())
}

fn main() {
    let fut = async {
        make_unit()?;
        
        Ok::<(), Error>(())
    };
}

Loading

Centril added a commit to Centril/rust that referenced this issue Aug 14, 2019
…ntril

When needing type annotations in local bindings, account for impl Trait and closures

Fix rust-lang#46680, fix rust-lang#63504, fix rust-lang#63506, fix rust-lang#40014, cc rust-lang#63502.
@nikomatsakis
Copy link
Contributor

@nikomatsakis nikomatsakis commented Aug 28, 2019

Discussing as part of a "triage effort". A few notes:

  • This isn't (necessarily) an inference failure: the original code snippet is somewhat underspecified, in that the return type of the async block can be any error type E that the Error value can be Into'd into.
  • What's needed is probably (a) a syntax to conveniently specify the error type and (b) a diagnostic that suggests said syntax.

We lack a syntax. So maybe we can give a better diagnostic that at least hints at the solution. Or maybe an extended error code description.

Loading

@estebank
Copy link
Contributor

@estebank estebank commented Aug 28, 2019

For this case, we probably could suggest a temporary local binding with an explicit type:

    let fut = async {
        let x: Result<_, Error> = make_unit();
        x?;
        Ok(())
    };

As for the syntax, we could borrow the closure syntax and allow something like async -> Result<(), Error> {} or async::<Result<(), Error> {}, but those are uuuugly.

CC #62570, as it is not the same error, but it is similar enough code that these two errors will likely happen in short temporal distance of each other.

Loading

@cramertj
Copy link
Member

@cramertj cramertj commented Aug 28, 2019

@estebank did you mean to include the ? after the x in your example above?

Loading

@estebank
Copy link
Contributor

@estebank estebank commented Aug 28, 2019

Yes, but was missing the final expr Ok(()) to be correctly equivalent the original code. Just updated it.

Loading

@cramertj
Copy link
Member

@cramertj cramertj commented Aug 28, 2019

@estebank That code still would not compile-- the error type annotation doesn't help there because it gets .into()'d in the ? usage. To make it work, you need to annotate the type of the final Ok value.

Loading

@estebank
Copy link
Contributor

@estebank estebank commented Aug 29, 2019

You're absolutely right. Need more coffee.

Loading

@programmerjake
Copy link
Contributor

@programmerjake programmerjake commented Aug 29, 2019

doesn't ? still use From rather than Into, or did I miss some happy RFC?

Loading

bors added a commit that referenced this issue Dec 11, 2019
Point at method call when type annotations are needed

- Point at method call instead of whole expression when type annotations are needed.
- Suggest use of turbofish on function and methods.

Fix #49391, fix #46333, fix #48089. CC #58517, #63502, #63082.

r? @nikomatsakis
bors added a commit that referenced this issue Dec 11, 2019
Point at method call when type annotations are needed

- Point at method call instead of whole expression when type annotations are needed.
- Suggest use of turbofish on function and methods.

Fix #49391, fix #46333, fix #48089. CC #58517, #63502, #63082.

r? @nikomatsakis
bors added a commit that referenced this issue Dec 13, 2019
Point at method call when type annotations are needed

- Point at method call instead of whole expression when type annotations are needed.
- Suggest use of turbofish on function and methods.

Fix #49391, fix #46333, fix #48089. CC #58517, #63502, #63082.

Fixes #40015

r? @nikomatsakis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants