Repository: rust
Issue: More helpful output for slightly-wrong dyn with multiple traits.
Labels: A-diagnostics,A-parser,P-low,T-compiler,D-confusing

I recently tried to [demonstrate why `dyn Trait1 + Trait2` doesn't work](https://www.youtube.com/watch?t=3801&v=xcygqF5LVmM&feature=youtu.be). I ended up writing ([all examples below on playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=448b239f9c24149069485dd748e47432)):

```rust
pub fn foo1(_: &dyn Drop + AsRef<str>) {}
```

and because I was in my editor, I only saw the first part of the error: "ambiguous `+` in a type". As a result, rather than follow the helpful compiler error

```
1 | pub fn foo1(_: &dyn Drop + AsRef<str>) {}
  |                 ^^^^^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(dyn Drop + AsRef<str>)`
```

I went ahead and tried to fix the syntax myself. Unfortunately, those only gave me _worse_ error messages. I tried:

---

```rust
pub fn foo2(_: &dyn (Drop + AsRef<str>)) {}
```

which gives

```
error: expected one of `(`, `)`, `::`, or `<`, found `+`
 --> src/lib.rs:3:27
  |
3 | pub fn foo2(_: &dyn (Drop + AsRef<str>)) {}
  |                           ^ expected one of `(`, `)`, `::`, or `<`

error: expected one of `->`, `;`, `where`, or `{`, found `)`
 --> src/lib.rs:3:40
  |
3 | pub fn foo2(_: &dyn (Drop + AsRef<str>)) {}
  |                                        ^ expected one of `->`, `;`, `where`, or `{`
```

---

I tried:

```rust
pub fn foo3(_: &dyn {Drop + AsRef<str>}) {}
```

Which gives

```
error: expected parameter name, found `{`
 --> src/lib.rs:5:21
  |
5 | pub fn foo3(_: &dyn {Drop + AsRef<str>}) {}
  |                     ^ expected parameter name

error: expected one of `!`, `(`, `)`, `,`, `?`, `for`, lifetime, or path, found `{`
 --> src/lib.rs:5:21
  |
5 | pub fn foo3(_: &dyn {Drop + AsRef<str>}) {}
  |                    -^ expected one of 8 possible tokens
  |                    |
  |                    help: missing `,`

error[E0224]: at least one trait is required for an object type
 --> src/lib.rs:5:17
  |
5 | pub fn foo3(_: &dyn {Drop + AsRef<str>}) {}
```

This one is particularly egregious as it suggests there's a missing `,`.

---

I tried:

```rust
pub fn foo4(_: &dyn <Drop + AsRef<str>>) {}
```

Which gives

```
error: expected identifier, found `<`
 --> src/lib.rs:7:21
  |
7 | pub fn foo4(_: &dyn <Drop + AsRef<str>>) {}
  |                     ^ expected identifier
```

---

I tried:

```rust
pub fn foo5(_: &(dyn Drop + dyn AsRef<str>)) {}
```

Which gives

```
error: expected one of `!`, `(`, `)`, `,`, `?`, `for`, lifetime, or path, found keyword `dyn`
 --> src/lib.rs:9:29
  |
9 | pub fn foo5(_: &(dyn Drop + dyn AsRef<str>)) {}
  |                            -^^^ expected one of 8 possible tokens
  |                            |
  |                            help: missing `,`

error[E0277]: the size for values of type `dyn Drop` cannot be known at compilation time
 --> src/lib.rs:9:16
  |
9 | pub fn foo5(_: &(dyn Drop + dyn AsRef<str>)) {}
  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `dyn Drop`
  = note: only the last element of a tuple may have a dynamically sized type
```

This one is even more problematic as it not only suggests there's a missing `,`, but also suggests that `dyn Drop` is the problem.

---

Ideally, all of these cases should point out that I probably meant `&(dyn Drop + AsRef<str>)`, and also give the friendly "only auto traits can be used as additional traits in a trait object" message.

The error messages are (currently) all the same on nightly.

See also discussion [on Twitter](https://twitter.com/jonhoo/status/1388310846258900999).