Repository: rust
Issue: Misleading error message talks about return value of closure when the issue is about Fn vs FnOnce
Labels: A-diagnostics,A-closures,T-compiler,D-confusing,D-terse

In this code:

```rust
pub struct Shared {}

pub trait State {
    fn new(shared: Rc<RefCell<Shared>>) -> Self where Self: Sized;
}

pub struct StateManager {
    factories: HashMap<String, Box<dyn Fn() -> Box<dyn State>>>,
    shared: Rc<RefCell<Shared>>
}

impl StateManager {
    pub fn new() -> Self {
        Self {
            factories: HashMap::new(),
            shared: Rc::new(RefCell::new(Shared {}))
        }
    }
    pub fn register_state<S: State + 'static>(&mut self, name: String) {
        let shared = self.shared.clone();
        self.factories.insert(name, Box::new(move || {
            // uncomment this to make it compile:
            // let shared = shared.clone();
            Box::new(S::new(shared)) as Box<dyn State>
        }) as Box<dyn Fn() -> Box<dyn State>>);
    }
}
```
[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9efce4d01d986d3decac7f581d5be7fc)

I expected to see this happen: An error that explains that the closure is `FnOnce` due to giving `shared` away.

Instead, this happened: An error that says the closure is not `dyn Fn()`, which appears to be talking about its return value. Note in particular the `help` note about wrapping it in a closure with no arguments.

The error is:
```
error[E0277]: expected a `std::ops::Fn<()>` closure, found `[closure@src/lib.rs:25:46: 29:10 shared:std::rc::Rc<std::cell::RefCell<Shared>>]`
  --> src/lib.rs:25:37
   |
25 |           self.factories.insert(name, Box::new(move || {
   |  _____________________________________^
26 | |             // uncomment this to make it compile:
27 | |             // let shared = shared.clone();
28 | |             Box::new(S::new(shared)) as Box<dyn State>
29 | |         }) as Box<dyn Fn() -> Box<dyn State>>);
   | |__________^ expected an `Fn<()>` closure, found `[closure@src/lib.rs:25:46: 29:10 shared:std::rc::Rc<std::cell::RefCell<Shared>>]`
   |
   = help: the trait `std::ops::Fn<()>` is not implemented for `[closure@src/lib.rs:25:46: 29:10 shared:std::rc::Rc<std::cell::RefCell<Shared>>]`
   = note: wrap the `[closure@src/lib.rs:25:46: 29:10 shared:std::rc::Rc<std::cell::RefCell<Shared>>]` in a closure with no arguments: `|| { /* code */ }
   = note: required for the cast to the object type `dyn std::ops::Fn() -> std::boxed::Box<dyn State>`
```
By moving things around a little bit, you get the expected error message:
```rust
pub fn register_state<S: State + 'static>(&mut self, name: String) {
    let shared = self.shared.clone();
    
    let closure: Box<dyn Fn() -> Box<dyn State>> = Box::new(move || {
        // uncomment this to make it compile:   
        // let shared = shared.clone();
        Box::new(S::new(shared)) as Box<dyn State>
    });
    
    self.factories.insert(name, closure);
}
```
[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c472f559ddb95739f3dfa95f9c74de9a)
```
error[E0507]: cannot move out of `shared`, a captured variable in an `Fn` closure
  --> src/lib.rs:29:29
   |
24 |         let shared = self.shared.clone();
   |             ------ captured outer variable
...
29 |             Box::new(S::new(shared)) as Box<dyn State>
   |                             ^^^^^^ move occurs because `shared` has type `std::rc::Rc<std::cell::RefCell<Shared>>`, which does not implement the `Copy` trait
```