-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Privatize constructors of tuple structs with private fields #38932
Conversation
Kicked off a crater run. |
Crater report: https://gist.github.com/nikomatsakis/1ab3b82ab09e83c587b6256c06da2b25 Root regressions, sorted by rank (checked means "investigated"):
|
There are 3 distinct regressions: All the regressions can be minimized like this:
The semantics Warning period may be non-trivial, but I'll try to look what |
@petrochenkov nice analysis, interesting example. I too am curious what @jseyfried and @nrc think =) cc @rust-lang/lang -- this has to do with the visibility of struct constructors, and the (somewhat odd, but at one time legal) pattern that breaks if you change it. Basically you could |
I'm in favor of this solution -- I think it's the cleanest way to guarantee that e.g. To implement a warning cycle, I would
|
I'm also in favour of this, seems like the sensible approach. |
@petrochenkov -- it seems like there is a general 👍 to this approach. Are you pursuing code for a warning period? @jseyfried has some suggestions here. |
Yes, I'll update the PR in a few days. |
ebda4aa
to
16d98fd
Compare
Updated with a compatibility lint (following the strategy from #38932 (comment)). |
16d98fd
to
a4e1795
Compare
☔ The latest upstream changes (presumably #39199) made this pull request unmergeable. Please resolve the merge conflicts. |
a4e1795
to
8de826e
Compare
Rebased. |
☔ The latest upstream changes (presumably #39060) made this pull request unmergeable. Please resolve the merge conflicts. |
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.
r=me modulo comments
|
||
fn main() { | ||
m::S; //~ ERROR tuple struct `S` is private | ||
S; //~ ERROR expected value, found struct `S` |
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.
Could we inform the user here that the tuple struct constructor S
is private?
We could use the same condition as the warning cycle, except that we would report if the constructor were not visible.
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.
Yeah, that would be useful, but I hoped to get rid of legacy_ctor_visibilities
together with the compatibility lint.
What I don't like is that this table is filled on all successful runs, but is actually needed very rarely.
Is there any way to map struct's DefId
into (ctor's DefId
+ ctor's ty::Visibility
) on demand without building tables in advance?
It'll also require extending metadata reading interface to obtain the same mapping for other crates. I really dislike adding code through the compiler that is necessary only for reporting a single special note, but well...
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 agree with @jseyfried that the warning seems nice
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.
Is there any way to map struct's DefId into (ctor's DefId + ctor's ty::Visibility) on demand without building tables in advance?
We could simplify a little by mapping the struct's DefId
to the ctor's &'a NameBinding<'a>
, but we'd still be building an extra table.
To avoid that, we could add a variant
NameBindingKind::TupleStruct(Def, &'a NameBinding<'a> /* ctor */)
and use that for tuple struct type bindings instead of NameBindingKind::Def
.
NameBindingKind
is well encapsulated, so that shouldn't be too big of a change -- still might not be worth it though.
@@ -224,6 +224,12 @@ declare_lint! { | |||
} | |||
|
|||
declare_lint! { | |||
pub LEGACY_CONSTRUCTOR_VISIBILITY, | |||
Deny, |
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.
Do we need to make this deny-by-default, given that there are three breaking crates in the wild?
While the warning cycle is a bit hacky, I think the risk of "false positives" is very low.
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.
3 is small, no?
I preferred deny-by-default mostly to avoid successfully compiling more illegal code by default.
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 policy is usually warn-by-default, then deny-by-default, no? But we can make an exception, though we should make an RFC bot request about it. Either way, we should contact the authors of the crates in question and/or submit PRs.
@rfcbot fcp merge This is a fix to a privacy oversight that allows people to observe whether a tuple struct with a private field was defined as a tuple struct or not, something which was not intended to be public. The problem is that people can do The question is whether to make this a WARN-by-default or DENY-by-default lint. The usual policy would be warn-by-default. There are currently three root crates breaking in the wild. There are a lot of affected crates out there (285?) but I believe that most of those will be unaffected in short term because of
Given the small number of affected crates, I think starting with deny-by-default is reasonable (in particular, since this can still be overridden by cap-lints, and so most crates should be unaffected until there is time to fix the problem). Hence the FCP "merge" request. But I'd like to hear others' opinions (including the authors of the affected crates). cc @rust-lang/compiler @rust-lang/core |
Team member @nikomatsakis has proposed to merge this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
Agreed that deny-by-default seems OK here. Glad to see this getting fixed! |
Regarding radiant, it looks like I just forgot a "super" here and it happens to work anyway because the root pub uses the struct as well. (?) |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
r? @jseyfried The code looks reasonable to me, but I think @jseyfried is better suited to really review this. |
@petrochenkov r=me with the diagnostics improvement. |
Updated with better diagnostics. |
@@ -11,6 +11,7 @@ | |||
fn main() { | |||
let Box(a) = loop { }; | |||
//~^ ERROR expected tuple struct/variant, found struct `Box` | |||
//~| ERROR expected tuple struct/variant, found struct `Box` |
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 is a compiletest bug. If one error has two labels, compiletest will require two "expected errors".
We're abusing RFC bot here (someday we want a mode just for getting team approval of a PR). There's not actually an FCP here; you can merge at any time. |
Excellent. |
📌 Commit d38a8ad has been approved by |
⌛ Testing commit d38a8ad with merge 558ea08... |
💔 Test failed - status-appveyor |
@bors retry |
⌛ Testing commit d38a8ad with merge 8060de2... |
💔 Test failed - status-appveyor |
@bors retry |
⌛ Testing commit d38a8ad with merge 5dc365f... |
💔 Test failed - status-travis |
That |
@bors: retry
…On Wed, Feb 1, 2017 at 6:30 AM, Vadim Petrochenkov ***@***.*** > wrote:
That curl issue again.
Looks like something persistent.
—
You are receiving this because you are on a team that was mentioned.
Reply to this email directly, view it on GitHub
<#38932 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAD95LA10zE6MuS8yIfT-rZN7iSi7GNDks5rYJbqgaJpZM4Ld0MC>
.
|
⌛ Testing commit d38a8ad with merge 43e169e... |
💔 Test failed - status-travis |
… On Wed, Feb 1, 2017 at 6:42 PM, bors ***@***.***> wrote:
💔 Test failed - status-travis
<https://travis-ci.org/rust-lang/rust/builds/197495794>
—
You are receiving this because you are on a team that was mentioned.
Reply to this email directly, view it on GitHub
<#38932 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAD95CiOYSExNQCXLrazDUXU4O2HRSVuks5rYUJ-gaJpZM4Ld0MC>
.
|
Privatize constructors of tuple structs with private fields This PR implements the strictest version of such "privatization" - it just sets visibilities for struct constructors, this affects everything including imports. ``` visibility(struct_ctor) = min(visibility(struct), visibility(field_1), ..., visibility(field_N)) ``` Needs crater run before proceeding. Resolves rust-lang/rfcs#902 r? @nikomatsakis
☀️ Test successful - status-appveyor, status-travis |
This PR implements the strictest version of such "privatization" - it just sets visibilities for struct constructors, this affects everything including imports.
Needs crater run before proceeding.
Resolves rust-lang/rfcs#902
r? @nikomatsakis