-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Fix diagnostic for cross crate private tuple struct constructors #85068
Conversation
…s with private fields. The more helpful diagnostic already existed but wasn't working if the struct in question was a re-export from a different crate.
r? @estebank (rust-highfive has picked a reviewer for you, use r? to override) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have one nitpick but I like it! Could you take a look to see if you can easily recover the span label that we are now missing in the last test?
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => { | ||
let parent = cstore.def_key(def_id).parent; | ||
if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) { | ||
self.r.struct_constructors.insert(struct_def_id, (res, vis, vec![])); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this block removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This match case would only get hit for non-re-exported structs' constructors which is why we would miss the cross-crate case to begin with. So for a given newtype constructor we would sometimes hit both the DefKind::Ctor
and DefKind::Struct
arms or only hit the DefKind::Struct
arm. It is the latter case where we didn't have the good diagnostics.
callback
here collects the Exports which end up processed by the method build_reduced_graph_for_external_crate_res
above:
rust/compiler/rustc_metadata/src/rmeta/decoder.rs
Lines 1084 to 1095 in 2bafe96
callback(Export { res, ident, vis, span }); | |
// For non-re-export structs and variants add their constructors to children. | |
// Re-export lists automatically contain constructors when necessary. | |
match kind { | |
DefKind::Struct => { | |
if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) { | |
let ctor_kind = self.get_ctor_kind(child_index); | |
let ctor_res = | |
Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); | |
let vis = self.get_visibility(ctor_def_id.index); | |
callback(Export { res: ctor_res, vis, ident, span }); | |
} |
So my PR just handles collecting struct_constructors
for diagnostics always in the DefKind::Struct
arm instead of relying on the Ctor
arm which isn't always present.
@@ -2,7 +2,7 @@ error[E0423]: cannot initialize a tuple struct which contains private fields | |||
--> $DIR/struct.rs:20:14 | |||
| | |||
LL | let ts = TupleStruct(640, 480); | |||
| ^^^^^^^^^^^ constructor is not visible here due to private fields |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems at first sight that the removed block might be responsible for the removal of this span_label.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason we actually had this span_label before was because this was one of the cases handled by the DefKind::Ctor
arm I removed above which you can see just always passed in an empty vec for the field visibilities. Now that we pass in the correct value there, not printing this message is actually correct since none of the fields are actually private! The reason for the error is because of #[non_exhaustive]
which unfortunately isn't handled very well right now. I can hopefully get to improving the non-exhaustive errors and diagnostics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case we should also change the error message.
I would like us to keep the constructor is not visible here due to private fields
label regardless. If you look at the other output it is missing as well. Don't get me wrong, the new note is fantastic, but missing primary labels are a potential problem: some people have trained themselves to not read the main message, in other cases tools that display tooltips in users' code rely on the primary label instead of the message because it is usually better in context. I made a mockup on the other test output of what I'd like to see in the future. I'd be inclined to merge this PR if you don't intend on continuing work, but I'd like a ticket open for the follow up tweaks.
@@ -2,7 +2,7 @@ error[E0423]: cannot initialize a tuple struct which contains private fields | |||
--> $DIR/struct.rs:20:14 | |||
| | |||
LL | let ts = TupleStruct(640, 480); | |||
| ^^^^^^^^^^^ constructor is not visible here due to private fields |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case we should also change the error message.
I would like us to keep the constructor is not visible here due to private fields
label regardless. If you look at the other output it is missing as well. Don't get me wrong, the new note is fantastic, but missing primary labels are a potential problem: some people have trained themselves to not read the main message, in other cases tools that display tooltips in users' code rely on the primary label instead of the message because it is usually better in context. I made a mockup on the other test output of what I'd like to see in the future. I'd be inclined to merge this PR if you don't intend on continuing work, but I'd like a ticket open for the follow up tweaks.
| ^^^ | ||
| | ||
note: constructor is not visible here due to private fields | ||
--> $DIR/issue-75907_b.rs:9:16 | ||
| | ||
LL | let Bar(x, y, z) = make_bar(); | ||
| ^ ^ private field | ||
| | | ||
| private field |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While looking at this again, I think we could make this slightly different, but it is not introduced by you:
| ^^^ | |
| | |
note: constructor is not visible here due to private fields | |
--> $DIR/issue-75907_b.rs:9:16 | |
| | |
LL | let Bar(x, y, z) = make_bar(); | |
| ^ ^ private field | |
| | | |
| private field | |
| ^^^ - - private field | |
| | | | |
| | private field | |
| constructor not visible here due to private fields |
@bors r+ |
📌 Commit 89300cd has been approved by |
…laumeGomez Rollup of 4 pull requests Successful merges: - rust-lang#85068 (Fix diagnostic for cross crate private tuple struct constructors) - rust-lang#85175 (Rustdoc cleanup) - rust-lang#85177 (add BITS associated constant to core::num::Wrapping) - rust-lang#85240 (Don't suggest adding `'static` lifetime to arguments) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Fixes #78708.
There was already some limited support for certain cross-crate scenarios but that didn't handle a tuple struct rexported from an inner module for example (e.g. the NonZero* types as seen in #85049).
Before:
After:
One question is if we should only collect the needed info for the cross-crate case after encountering an error instead of always doing it. Perf run perhaps to gauge the impact.