Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upRFC: Type privacy and private-in-public lints #2145
Conversation
petrochenkov
added some commits
Sep 10, 2017
aturon
self-assigned this
Sep 11, 2017
aturon
added
Ergonomics Initiative
T-lang
labels
Sep 11, 2017
This comment has been minimized.
This comment has been minimized.
|
Thanks much, @petrochenkov! This came out of a long-running discussion on internals with oversight from the lang team. I'm going to go ahead and kick off the full review process: @rfcbot fcp merge |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Sep 13, 2017
•
|
Team member @aturon 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. |
rfcbot
added
the
proposed-final-comment-period
label
Sep 13, 2017
This comment has been minimized.
This comment has been minimized.
|
I've now reviewed this RFC myself, and have to say: I'm very impressed by this writeup (and continue to love the Guide/Reference distinction)! Kudos. I don't have a ton to add to the technical content, but as to the unresolved question around associated types: I think the approach taken here is quite reasonable, and at any rate is the conservative choice. It does mean that there's a slight inconsistency in the style of the rules, but I expect this to be a much smaller papercut than the current rules are. I'm also a fan of having the new lints be based on reachability. That was deemed problematic before when determining the meaning of privacy, but as a lint we have a lot more leeway to be smart about the analysis. All told: this seems like a total slam dunk to me. |
This comment has been minimized.
This comment has been minimized.
|
Just to be clear, the privacy rules description here changes nothing and the only change is changing the pub-in-priv error into lints? Note that type privacy is not quite as bullet proof as made out here - if you can name the type you know its size and thus can transmute it to another type and get access to its data or even mutate it (possibly via C interop) therefore there is some benefit in the conservative pub-in-priv error over type privacy (its also not clear to me how this plays with macro hygiene). I think we should not have two separate lints for the primary/secondary variations - seems like too much detail to be worth exposing to users. Otherwise I am wildly in favour of this RFC! I would actually like to go a bit further (though perhaps not right now in this RFC) - I'd like to have two lints - one which works like the current error at the module level and is warning (or even off) by default and one that works at crate scope and is error by default. My reasoning is that within a crate, a privacy leak is usually just annoying, nothing worse. But leaking private data outside a crate could easily be a security vulnerability. |
This comment has been minimized.
This comment has been minimized.
Yes.
Type privacy checks are unhygienic currently, i.e. private types leaked through macros 2.0 will still generate errors to prevent cases like this struct Priv {}
pub macro m() {
Priv
}
// Another module
type A = m!(); // Priv is leakedThe rule can be relaxed to ignore intermediate types/values used by macros, but not "returned" by them, but this requires some more thought, has linkage implications and I don't want to include it in this RFC.
I separated them due to very different error probabilities.
I don't understand this paragraph.
I don't understand this as well. |
This comment has been minimized.
This comment has been minimized.
I see the benefit, but I'm not sure its worth the cost of having two separate lints.
I don't think that is necessary to call transmute - the compiler will know the size and so you can transmute, aiui.
Hmm, I guess you can always convert
Let's discuss this later. My intuition is that leaking a private type out of a module isn't that important, but leaking it out of a crate is. |
This comment has been minimized.
This comment has been minimized.
|
Apologies for my delay in responding to this RFC! The RFC itself is well-specified and the guide and reference-level explanations make sense to me. However, I'm struggling to understand the motivations behind this change. Primarily, it seems to me like allowing a private type or trait to appear in a public interface is nearly always going to result in a sub-par end-user experience. Documentation won't be able to provide information about the non-public type and values of type will be strangely unusable. One major point that came up in previous discussions was the ability to make a private supertrait of a public trait so as to prevent users from providing their own implementation. Personally, I think this design would be really confusing to me as an end-user of a library: I'd still try to implement the trait, but then I'd get confused and stuck trying to understand how to properly name and implement a trait that I could clearly see in the documentation. If this is a primary motivation for this RFC, I'd strongly prefer we look to more natural and self-explanatory solutions such as first-class sealed traits, rather than hard-to-understand exceptions to Rust's privacy rules. @rfcbot concern motivation |
This comment has been minimized.
This comment has been minimized.
The current Rules are based on local The private-in-public rules can be potentially relaxed in any way since they are not technically necessary (and not sufficient). The problem is that reachability-based rules that match those expectations are pretty vague, especially in presence of macros 2.0, so it would be really unfortunate to make them hard language rules rather than lints. Those lints can certainly be deny-by-default (especially |
This comment has been minimized.
This comment has been minimized.
|
@petrochenkov The "perfect derive" question seems much thornier to me:
Allowing these types (e.g. But perhaps we're thinking along the same lines: IMO bounds should be able to use private types, and it should be the compiler's and rustdoc's responsibility to translate those bounds into "external-facing" terms: struct Wrap<T>(T);
pub struct Foo<T>(Wrap(T));
impl<T> Clone for Wrap<T> where T: Clone + Copy + Sync {
....
}
// Autogenerated by derive:
impl<T> Clone for Foo<T> where Wrap<T>: Clone {
....
}
// translates to this in compiler errors / rustdoc:
"Foo<T> implements Clone only if T: Clone + Copy + Sync"IIRC, bounds propagations like this are already done in some compiler errors. I wouldn't think it would be too much work to extend it to allow for things like I don't want to support writing code that makes non- |
This comment has been minimized.
This comment has been minimized.
Me too! It's simple if you know the rules, but it's not expected for some reason. |
This comment has been minimized.
This comment has been minimized.
Aaand the lint about this is already a part of rust-lang/rust#44660 (this is not a universally supported opinion though). |
This comment has been minimized.
This comment has been minimized.
|
As I'm the only remaining holdout on this RFC, I thought I should directly address some of the comments that had been made previously in support of the RFC. I reread the internals thread and noticed this comment by @nikomatsakis:
As I said in my earlier comment, I'm worried that allowing users to ignore the public/private declaration rules will give them an incorrect understanding of how privacy works in Rust, and in particular an incorrect impression of the meaning of I'm also worried that users won't understand why their particular usage is "incorrect," and so rather than reaching out, learning about privacy, and fixing the lints, they'll just |
This comment has been minimized.
This comment has been minimized.
|
So, to me, a key point here is having a clear delineation between what is a hard error versus a lint. Personally, I prefer to tie hard errors to crisp, hard, valuable guarantees. I think there's a core set of such guarantees related to privacy that should, indeed, be a hard error, because you crucially rely on these guarantees when reasoning about your code. On the other hand, lints are for things that are likely bugs or non-standard style, but are not critical components of guarantees. That's why, for example, in the modules RFC the "misuse" of Yes, people are more likely to ignore lints, but just as importantly, people can ignore lints when prototyping or first learning, and still get a useful, runnable result. Yes, that may represent a missed teaching opportunity, but the timing of teaching is important -- you're often in the middle of trying to do something else when you hit an error like this, and not in a great place to stop and learn something about the privacy system. Finally, there's a strong enough culture in Rust that |
This comment has been minimized.
This comment has been minimized.
|
Thanks for your responses! After talking this through, I feel like you've both listened to and understood my concerns. I'd still personally prefer alternative solutions that don't allow private types to appear in public interfaces, but I'm confident that we can find solutions to make this case more ergonomic. For posterity's sake: as part of stabilizing this feature (or shortly after stabilizing this feature) I think there should be a work item to experiment with making the compiler and rustdoc omit the names of private items from types, bounds, and error messages. I believe this could prevent a great deal of confusion when using libraries that have private types their public interfaces. |
cramertj
added
final-comment-period
and removed
proposed-final-comment-period
labels
Sep 25, 2017
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Sep 25, 2017
|
|
rfcbot
added
the
final-comment-period
label
Sep 25, 2017
petrochenkov
referenced this pull request
Oct 2, 2017
Closed
private_in_public warning for private methods #40844
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Oct 5, 2017
|
The final comment period is now complete. |
This was referenced Nov 18, 2017
bors
added a commit
to rust-lang/rust
that referenced
this pull request
Nov 18, 2017
bors
added a commit
to rust-lang/rust
that referenced
this pull request
Dec 21, 2017
This comment has been minimized.
This comment has been minimized.
vks
commented
Feb 1, 2018
Maybe open an issue for this? |
aturon
referenced this pull request
Feb 7, 2018
Open
Tracking issue for RFC #2145: Type privacy and private-in-public lints #48054
aturon
merged commit 28bdbbc
into
rust-lang:master
Feb 7, 2018
This comment has been minimized.
This comment has been minimized.
|
This RFC has been (very belatedly!) merged! |
petrochenkov commentedSep 10, 2017
•
edited
Type privacy rules are documented.
Private-in-public errors are relaxed and turned into lints.
Rendered