Open russelltg opened 5 years ago
Opened https://github.com/rust-lang/rust/issues/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: https://github.com/rust-lang/rust/issues/49391, https://github.com/rust-lang/rust/issues/38508, https://github.com/rust-lang/rust/issues/46333, https://github.com/rust-lang/rust/issues/46680, https://github.com/rust-lang/rust/issues/48089, https://github.com/rust-lang/rust/issues/61152, https://github.com/rust-lang/rust/issues/58517 and https://github.com/rust-lang/rust/issues/63082.
(larger work around ?
tracked in https://github.com/rust-lang/rust/issues/31436)
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>(())
};
}
Discussing as part of a "triage effort". A few notes:
Error
value can be Into
'd into. 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.
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 https://github.com/rust-lang/rust/issues/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.
@estebank did you mean to include the ?
after the x
in your example above?
Yes, but was missing the final expr Ok(())
to be correctly equivalent the original code. Just updated it.
@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.
You're absolutely right. Need more coffee.
doesn't ?
still use From
rather than Into
, or did I miss some happy RFC?
Current output:
error[[E0282]](https://doc.rust-lang.org/nightly/error_codes/E0282.html): type annotations needed
--> src/main.rs:11:9
|
11 | Ok(())
| ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
|
help: consider specifying the generic arguments
|
11 | Ok::<(), E>(())
| +++++++++
The only thing left is for inference to detect that E
could have been Error
and suggest that.
This seems related to #42424, except I don't see an obvious workaround like in #42424.
Fails with the error
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 addimpl std::future::Future<Output=Result<(), Error>>
as a type annotation, it also fails to compile becauseimpl Trait
is only allowed as return types and argument types.Playground link