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 message for closure with async block needs improvement #68119

Open
tmandry opened this issue Jan 11, 2020 · 2 comments
Open

Error message for closure with async block needs improvement #68119

tmandry opened this issue Jan 11, 2020 · 2 comments

Comments

@tmandry
Copy link
Contributor

@tmandry tmandry commented Jan 11, 2020

Playground

fn do_stuff(foo: Option<Foo>) {
    require_fn_trait(|| async {
        if foo.map_or(false, |f| f.foo()) {
            panic!("foo");
        }
        //ready(())
    })
}

gives

error[E0507]: cannot move out of `foo`, a captured variable in an `Fn` closure
  --> src/lib.rs:14:31
   |
13 |   fn do_stuff(foo: Option<Foo>) {
   |               --- captured outer variable
14 |       require_fn_trait(|| async {
   |  _______________________________^
15 | |         if foo.map_or(false, |f| f.foo()) {
   | |            ---
   | |            |
   | |            move occurs because `foo` has type `std::option::Option<Foo>`, which does not implement the `Copy` trait
   | |            move occurs due to use in generator
16 | |             panic!("foo");
17 | |         }
18 | |         //ready(())
19 | |     })
   | |_____^ move out of `foo` occurs here
   |
help: consider borrowing the `Option`'s content
   |
14 |     require_fn_trait(|| async {
15 |         if foo.map_or(false, |f| f.foo()) {
16 |             panic!("foo");
17 |         }
18 |         //ready(())
19 |     }.as_ref())
   |

Note move occurs due to use in generator. Also, the code is being output twice, for some reason.

If you take this out of the async context by removing async and uncommenting ready(()), you get a better suggestion to use as_ref() and an all-around cleaner error message:

error[E0507]: cannot move out of `foo`, a captured variable in an `Fn` closure
  --> src/lib.rs:15:12
   |
13 | fn do_stuff(foo: Option<Foo>) {
   |             --- captured outer variable
14 |     require_fn_trait(|| {
15 |         if foo.map_or(false, |f| f.foo()) {
   |            ^^^
   |            |
   |            move occurs because `foo` has type `std::option::Option<Foo>`, which does not implement the `Copy` trait
   |            help: consider borrowing the `Option`'s content: `foo.as_ref()`

Thanks to @JakeEhrlich for originally reporting this.

@tmandry tmandry changed the title Error message for closure with async block mentions generators Error message for closure with async block needs improvement Jan 13, 2020
@nikomatsakis

This comment has been minimized.

Copy link
Contributor

@nikomatsakis nikomatsakis commented Jan 14, 2020

It took me a while to process what's going on here. I guess the biggest problem is the "move of foo occurs here" that highlights the whole async block.

In contrast, we don't show (for closures) the "closure creation" as the point of a move (although it technically is). We just show the point within the closure body that's responsible.

Looking more closely at the example, it seems like there are actually several moves happening

  • into the outer closure
  • into the async block
  • then into map_or call

and so I guess we are suppressing one but not the rest. I'd have to go digging a bit to give more specifics on how to fix.

@tmandry

This comment has been minimized.

Copy link
Contributor Author

@tmandry tmandry commented Jan 14, 2020

@rustbot modify labels to +AsyncAwait-OnDeck

Good diagnostics are a priority

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.