Repository: rust
Issue: Confusing/unhelpful errors trying to map over a tree structure
Labels: A-diagnostics,T-compiler,D-newcomer-roadblock

(Filing at [request of @estebank on Twitter](https://twitter.com/ekuber/status/1447509333185548290); I ran into these three years ago, but I just did a run through the playground and nothing relevant has changed).

I wrote up an experience report a few year ago of trying to map a function over a binary tree in Rust, coming to Rust with experience in a bunch of languages, including C++. I made a bunch of "rookie mistakes", but at basically every step the compiler was unhelpful, often suggesting actively incorrect fixes.

The full saga is here: 

https://nelhagedebugsshit.tumblr.com/post/173312515628/experience-report-trying-to-map-over-over-a

This might be multiple issues, but I don't have a sense of which of these are or aren't tractable to improve.

I'll highlight two that seem tractable to me as an outsider; I'm happy to split these into separate issues on request.

## Dropped `&mut` in "did you mean" for incorrect function signature:

Given the following code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=eeef2edaef89405092831df76448110d

```rust
fn map_tree<F>(tree: &Rc<Tree>, &mut f: F) -> Rc<Tree>
where
    F: FnMut(Rc<Tree>) -> Rc<Tree>,
{
    match &**tree {
        &Tree::Leaf(_) => f(Rc::clone(tree)),
        &Tree::Node(ref l, ref r) => Rc::new(Tree::Node(map_tree(&l, f), map_tree(&r, f))),
    }
}
```

(Note that the author has written `&mut f: F`, but means `f: &mut F` -- an easy mistake IMO)

The current output is:

```
error[E0308]: mismatched types
 --> src/main.rs:9:33
  |
9 | fn map_tree<F>(tree: &Rc<Tree>, &mut f: F) -> Rc<Tree>
  |             -                   ^^^^^^---
  |             |                   |       |
  |             |                   |       expected due to this
  |             |                   expected type parameter `F`, found `&mut _`
  |             |                   help: did you mean `f`: `&F`
  |             this type parameter
  |
  = note: expected type parameter `F`
          found mutable reference `&mut _`
```

The suggestion has dropped the `&mut` entirely; If the compiler had been able to suggest `f: &mut F`, that would have been correct and much more helpful to me.

## Confusing error when failing to borrow a closure:

Given this Rust code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=cbff4c84eb58a289b9e9c75234d22d58
```rust
fn map_tree<F>(tree: &Rc<Tree>, f: &mut F) -> Rc<Tree>
where
    F: FnMut(Rc<Tree>) -> Rc<Tree>,
{ … }

pub fn main() {
    let tree = Rc::new(Tree::Node(Rc::new(Tree::Leaf(0)), Rc::new(Tree::Leaf(1))));
    let mut sum = 0;
    map_tree(&tree, |node| {
        match *node {
            Tree::Leaf(i) => sum = sum + i,
            _ => unreachable!(),
        }
        node
    });
    print!("sum={}", sum);
}
```

The compiler currently prints:

```
error[E0282]: type annotations needed
  --> src/main.rs:22:22
   |
22 |     map_tree(&tree, |node| {
   |                      ^^^^ consider giving this closure parameter a type
   |
   = note: type must be known at this point
```

The correct fix here, as far as I can tell, is *not* to add a type, but simply to mutably borrow the closure: 

```rust
    map_tree(&tree, &mut |node| {
    …
    }
```