Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
yoshuawuyts opened this issue Aug 25, 2020 · 1 comment · Fixed by #76499
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-visibility Area: Visibility / privacy. D-confusing Diagnostics: Confusing error or lint that should be reworked.

Comments

@yoshuawuyts
Copy link
Member

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!

@jyn514 jyn514 added A-diagnostics Area: Messages for errors, warnings, and lints A-visibility Area: Visibility / privacy. D-confusing Diagnostics: Confusing error or lint that should be reworked. labels Aug 25, 2020
@guswynn
Copy link
Contributor

guswynn commented Sep 3, 2020

I may be interested in helping make this better (this definitely has bitten me before), but I am new to rustc, so I am asking zulip for implementation advice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-visibility Area: Visibility / privacy. D-confusing Diagnostics: Confusing error or lint that should be reworked.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants