Skip to content

"surprisingly hard things" #22

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

Closed
nikomatsakis opened this issue Jul 9, 2019 · 8 comments
Closed

"surprisingly hard things" #22

nikomatsakis opened this issue Jul 9, 2019 · 8 comments
Assignees

Comments

@nikomatsakis
Copy link
Contributor

In the async foundations meeting today we discussed the idea of adding a "surprisingly hard things" chapter that lists out tricky scenarios and the workarounds to help get people unstuck. The hope would be that most of these things will eventually be fixed in some way. =)

This issue is meant to collect some possible topics:

@yoshuawuyts
Copy link
Member

yoshuawuyts commented Jul 29, 2019

We should mention futures-trait as a workaround for async fn in traits.

#![feature(async_await)]

use async_trait::async_trait;

#[async_trait]
trait View {
    async fn render(&self);
}

struct Modal;

#[async_trait]
impl View for Modal {
    async fn render(&self) {
        self.render_fullscreen().await;
    }
}

@cramertj cramertj self-assigned this Jul 30, 2019
@cramertj
Copy link
Member

hinting at error types in async blocks would be a good addition here: rust-lang/rust#63502

@nikomatsakis
Copy link
Contributor Author

Another thing that would be good to include:

https://users.rust-lang.org/t/mutexguard-cannot-be-sent-inside-future-generator/21584

the fact that the await analysis is approximate and captures "too much"

@Nemo157
Copy link
Member

Nemo157 commented Aug 19, 2019

To extend the error types in async blocks, there are situations where the final annotated return triggers a warning, mentioned by @udoprog on Discord:

Since the loop doesn't terminate the last statement will not be reached, so it's marked as unreachable. But if I remove it, how can I best hint what the return value is for the block?

let future = async {
  loop {
    task().await?;
  }

  Ok::<_, Error>(())
};

eventually impl_trait_in_bindings or type annotations on expressions might be able to solve this, but is there a better solution than #[allow(dead_code)] for now?

#![feature(impl_trait_in_bindings)]
let future: impl Future<Output = Result<_, Error>> = async { ... };

@ghost
Copy link

ghost commented Aug 19, 2019

@Nemo157 Could that be a type inference problem?

The following code doesn't compile either:

use std::fs::File;

fn main() {
    let f = || {
        File::open("a.txt")?;
        Ok(())
    };
}
error[E0282]: type annotations needed for `[closure@src/main.rs:4:13: 7:6]`
 --> src/main.rs:5:9
  |
4 |     let f = || {
  |         - consider giving `f` the explicit type `[closure@src/main.rs:4:13: 7:6]`, with the type parameters specified
5 |         File::open("a.txt")?;
  |         ^^^^^^^^^^^^^^^^^^^^ cannot infer type

If all uses of ? in a closure have the same error type, then I think that error type should be used for the whole closure. That could be a totally reasonable inference behavior. The same applies to async blocks.

@Nemo157
Copy link
Member

Nemo157 commented Aug 19, 2019

Yes, it's a type inference issue similar to the one @cramertj linked above (rust-lang/rust#63502). Until there is some way to specify the type (e.g. let f = || -> io::Result<_> { ... } in your example), then there needs to be a workaround to drive the inference to choose the correct value, as mentioned in that issue the simplest way is adding a fully typed return, but that runs afoul of dead_code with infinite loops.

Even if ? was somehow able to propagate a default to inference there would still be cases where you have multiple error types and need some way to specify the type. (There was some discussion of being able to explicitly annotate async and try blocks somewhere, but I don't remember which issue it was on).

@cramertj
Copy link
Member

cramertj commented Sep 6, 2019

Fixed by #36

@cramertj cramertj closed this as completed Sep 6, 2019
@estebank
Copy link

estebank commented Sep 6, 2019

@stjepang current output:

error[E0282]: type annotations needed for the closure `fn() -> std::result::Result<(), _>`
 --> src/main.rs:5:9
  |
5 |         File::open("a.txt")?;
  |         ^^^^^^^^^^^^^^^^^^^^ cannot infer type
help: give this closure an explicit return type without `_` placeholders
  |
4 |     let f = || -> std::result::Result<(), _> {
  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants