Skip to content

Zero member tuple struct should warn on incorrect construction #87181

Closed
@edward-shen

Description

@edward-shen

Hey folks, this just bit me so and took a bit to figure out, so I'd thought I'd file an issue for this admittedly niche issue.

Given the following code: playground

trait Foo {
    fn get(&self);
}

struct Bar<T>(T);

struct Inner();

impl Foo for Inner {
    fn get(&self) { }
}

fn main() {
    let thing = Bar(Inner);
    thing.0.get();
}

The current output is:

error[E0599]: no method named `get` found for fn item `fn() -> Inner {Inner}` in the current scope
  --> src/main.rs:16:13
   |
16 |     thing.0.get();
   |             ^^^ method not found in `fn() -> Inner {Inner}`
   |
   = note: `thing.0` is a function, perhaps you wish to call it
   = help: items from traits can only be used if the trait is implemented and in scope
note: `Foo` defines an item `get`, perhaps you need to implement it
  --> src/main.rs:2:1
   |
2  | trait Foo {
   | ^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

Ideally the output should look like:

error[E0599]: no method named `get` found for fn item `fn() -> Inner {Inner}` in the current scope
  --> src/main.rs:16:13
   |
16 |     thing.0.get();
   |             ^^^ method not found in `fn() -> Inner {Inner}`
   |
   = note: `thing.0` is a function, perhaps you wish to call it
   = note: `Inner` is a tuple struct with zero fields, perhaps you wish to initialize it instead: `Bar(Inner())`
   = help: items from traits can only be used if the trait is implemented and in scope
note: `Foo` defines an item `get`, perhaps you need to implement it
  --> src/main.rs:2:1
   |
2  | trait Foo {
   | ^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

This was an extremely confusing error message for me, as I suddenly had a fn() -> Inner type out of no where in my code! Of course, this was a simplified issue, but it's not immediately obvious that 1. a unit struct is actually a function returning its own type, and 2. the problem was due to the fact that a unit struct is not the same as a zero-member tuple struct.

This was extracted out of a much more complex error message, where the only hint to the actual problem was that the unit struct "constructor" didn't satisfy the trait bound, which pointed to a construction issue.

Not quite sure whether or not it's possible to actually implement a suggestion as written, but perhaps even a check between Inner vs Inner() might be a good note to have?

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsE-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.T-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