Skip to content

[diagnostics] Attempting to destructure a private field in a public tuple struct yields confusing error message #75907

Closed
@yoshuawuyts

Description

@yoshuawuyts

This is the destructure counterpart of #75906

Overview

Attempting to destructure a private field in a public tuple struct yields a confusing error message. Given the following code:

mod foo {
    pub(crate) struct Bar{inner: u8}
    
    pub(crate) fn make_bar() -> Bar {
        Bar{ inner: 12 }
    }
}

use foo::{Bar, make_bar};

fn main() {
    let Bar{ inner } = make_bar();
    dbg!(inner);
}

The following error is generated:

error[E0451]: field `inner` of struct `foo::Bar` is private
  --> src/main.rs:12:14
   |
12 |     let Bar{ inner } = make_bar();
   |              ^^^^^ private field

This seems quite helpful: some field is private, so we can infer we probably should make it public instead. However when we convert the code to a tuple struct things become more confusing:

mod foo {
    pub(crate) struct Bar(u8);
    
    pub(crate) fn make_bar() -> Bar {
        Bar(12)
    }
}

use foo::{Bar, make_bar};

fn main() {
    let Bar(y) = make_bar();
}

The following error is generated:

error[E0532]: expected tuple struct or tuple variant, found struct `Bar`
  --> src/main.rs:12:9
   |
12 |     let Bar(y) = make_bar();
   |         ^^^ constructor is not visible here due to private fields

The error message itself doesn't point us to the problem (expected tuple struct or tuple variant, found struct Bar), and mentioning a constructor in the code block isn't helpful either. After all we're not trying to construct anything; we're trying to destruct.

Proposed solution

When accessing a private field in a tuple struct rustc already generates pretty good errors:

    let x = make_bar();
    dbg!(x.0);
error[E0616]: field `0` of struct `foo::Bar` is private
  --> src/main.rs:13:12
   |
13 |     dbg!(x.0);
   |            ^ private field

When destructuring tuple structs these errors would be accurate as well:

error[E0616]: field `0` of struct `foo::Bar` is private
  --> src/main.rs:12:9
   |
12 |     let Bar(y) = make_bar();
   |             ^ private field

We could take it even further and suggest a fix for this as well:

error[E0616]: field `0` of struct `foo::Bar` is private
  --> src/main.rs:12:9
   |
12 |     let Bar(y) = make_bar();
   |             ^ private field
   |             |
   |             help: declare the struct's fields as public: `struct Bar(pub(crate) u8);`

Conclusion

In this issue I've shown an incorrect error message that occurs when attempting to destructure a private field in a tuple-struct, and made suggestions on how we can improve this.

I hope this is helpful. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-visibilityArea: Visibility / privacyD-confusingDiagnostics: Confusing error or lint that should be reworked.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions