Skip to content

More helpful output for slightly-wrong dyn with multiple traits. #84772

Open
@jonhoo

Description

@jonhoo

I recently tried to demonstrate why dyn Trait1 + Trait2 doesn't work. I ended up writing (all examples below on playground):

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:


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:

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:

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:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-parserArea: The lexing & parsing of Rust source code to an ASTD-confusingDiagnostics: Confusing error or lint that should be reworked.P-lowLow priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions