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 uppub(restricted) item #1422
Conversation
pnkfelix
added some commits
Dec 21, 2015
oli-obk
reviewed
Dec 21, 2015
|
|
||
| (You may be wondering: "Could we move that `impl S` out to the | ||
| top-level, out of `mod a`?" Well ... see discussion in the | ||
| [unresolved questions][def-outside-restriction].) |
This comment has been minimized.
This comment has been minimized.
oli-obk
Dec 21, 2015
Contributor
I don't find this to be a convincing example. You could just leave out the pub(a) and the example would work right now just as expected. Adding impls inside submodules is imo the correct way to say it's only accessible in there. The example should probably be showing two submodules accessing the same function. But then it doesn't fit here, but to to the unresolved question point.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
I currently emulate this with traits defined at the level that needs visibility, but it's a lot of annoying boilerplate: https://github.com/sfackler/rust-postgres/blob/master/src/lib.rs#L1437-L1487 |
petrochenkov
reviewed
Dec 21, 2015
|
|
||
| The main problem with this approach is that we tried it, and it | ||
| did not work well: The implementation was buggy, and the user-visible | ||
| error messages were hard to understand. |
This comment has been minimized.
This comment has been minimized.
petrochenkov
Dec 21, 2015
Contributor
Note, that reachability analysis is already performed by the privacy pass. Its results are used by rustdoc, dead code lint, stability and link-time-reachability passes, but not by privacy itself.
It's also less buggy than it was.
petrochenkov
reviewed
Dec 21, 2015
| Or does it just mean that `J`, despite being defined in `mod b`, is | ||
| itself not accessible in `mod b`? | ||
|
|
||
| pnkfelix is personally inclined to make this sort of thing illegal, |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
petrochenkov
Dec 22, 2015
Contributor
If arbitrary non-nested paths are permitted + a path list can be used instead of a single path pub(path1, path2, path3), then it will look more and more like friend from C++
:horror:
This comment has been minimized.
This comment has been minimized.
|
I like the idea, but I'm not sure about the syntax, you propose. |
This comment has been minimized.
This comment has been minimized.
|
I like the general direction, although I mostly have concerns about the implementation side, the current privacy system is not well formalized and three its main components - privacy checker itself, private-in-public checker and reachability analysis often work based on different assumptions and contradict to each other. Together with this and the new macro privacy system from @nrc it may bring some chaos. Also, fixing rust-lang/rust#30079 or relaxing the rules to allow
will probably involve implementing some rudimentary form of |
This comment has been minimized.
This comment has been minimized.
|
It would be really nice to try making |
nrc
reviewed
Dec 21, 2015
| tree." | ||
|
|
||
| The current `crate` is one such tree, and would be expressed via: | ||
| `pub(crate) item`. Other trees can be denoted via a path employed in a |
This comment has been minimized.
This comment has been minimized.
nrc
Dec 21, 2015
Member
We could have pub(::) instead of pub(crate), this would mean only having a single syntax, at the expense of grotesque ugliness.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
oli-obk
Dec 22, 2015
Contributor
alternatively crate could be allowed at the beginning of paths, thus making this a single syntax
This comment has been minimized.
This comment has been minimized.
pnkfelix
Feb 11, 2016
Author
Member
But then people will complain about having more than one way to do things (in this case, writing absolute paths) right?
This comment has been minimized.
This comment has been minimized.
|
Big Maybe I haven't worked on large enough libraries, but I am not sure that anything more powerful than
|
nrc
reviewed
Dec 21, 2015
| subtrees, narrow the feature to just `pub(crate) item`, so that one | ||
| chooses either "module private" (by adding no modifier), or | ||
| "universally visible" (by adding `pub`), or "visible to just the | ||
| current crate" (by adding `pub(crate)`). |
This comment has been minimized.
This comment has been minimized.
nrc
Dec 21, 2015
Member
I'm strongly against this alternative - I think it is ill-advised to make crates more significant than they already are - we would end up with two layers of modularisation. I prefer to keep crates as essentially file-system artefacts.
This comment has been minimized.
This comment has been minimized.
pnkfelix
Dec 21, 2015
Author
Member
Obviously I agree with @nrc; otherwise this RFC would have been written to just suggest pub(crate) on its own.
Of course we can see there are people on the other side of this debate; I've seen two commenters already state that they think pub(crate) may suffice on its own.
@nrc I am curious if you can come up with other use-cases for pub(path) beyond the hypothetical crate-merging refactoring tool that I sketched in the text of this subsection.
- Well, of course there is the obvious "some crates are large enough to warrant privacy controls within the crate, that are more fine-grained than just
pub/pub(crate)/private
I actually rather likes the proposal from @petrochenkov that we might roll this out in stages, with pub(crate) very early on, and adding pub(path) later after convincing the community at large that it is a good thing too.
Except I might advocate putting in pub(crate) before we tighten up the rules for privacy at large, for the precise reason described in the RFC: giving people the ability to express pub(crate) will encourage them to fix their code to say something closer to what they mean now and stop exploiting bugs in the privacy system to express such structures, which will give us more freedom to tighten up privacy (and tell them to use pub(crate) in the warnings emitted during warning cycle period).
This comment has been minimized.
This comment has been minimized.
petrochenkov
Dec 21, 2015
Contributor
before we tighten up the rules for privacy at large
I don't expect noticeable breakage from privacy in the future, most practically significant holes are closed now. Regarding the existing private_in_public warnings, I don't think pub(crate) will help much, but e.g. relaxing rules on trait bounds or alias substitution certainly will.
This comment has been minimized.
This comment has been minimized.
withoutboats
Dec 21, 2015
Contributor
I think it is ill-advised to make crates more significant than they already are - we would end up with two layers of modularisation.
I agree that this is not ideal, but how is this not already the case? Coherence rules operate at the crate rather than module level, extern crate declarations and cargo dependencies are in themselves not transparent, etc. There is already a pretty big difference in the relation between modules inside my crate and relations with modules outside of it.
This comment has been minimized.
This comment has been minimized.
petrochenkov
Dec 21, 2015
Contributor
With regards to privacy, crates are also important, as units of compilation - some code or metadata can potentially be omitted from the compiled crate if it can be proven that it is not accessible from other crates.
This comment has been minimized.
This comment has been minimized.
bstrie
Dec 22, 2015
Contributor
@nrc I think the battle against crates as a separate unit of modularization has long been lost. The crate vs. mod distinction already matters for circular dependencies, inlining, and incremental recompilation. I don't see any danger to embracing this distinction even further.
@pnkfelix I have indeed seen people asking for "crate-level visibility" for years now (I'd be surprised if there isn't an old RFC for it somewhere), so paring down this proposal to merely pub(crate) may very well be viable. And in that case you can even consider simplifying the syntax to just pub crate or crate pub or something.
This comment has been minimized.
This comment has been minimized.
pnkfelix
Dec 22, 2015
Author
Member
paring down this proposal to merely
pub(crate)may very well be viable. And in that case you can even consider simplifying the syntax to justpub crateorcrate pubor something.
I am pretty strongly opposed to adopting a syntax that isn't future-extensible to pub(path) ... pub in crate <item> (which then supports e.g. pub in path <item>) might work, though visually I think I prefer the parentheses.
This comment has been minimized.
This comment has been minimized.
|
The typeck point-of-view is that associated items are as private as their containing traits and that all types are basically public. I am not sure about the motivation for the no-privates-in-public rule (even reading the comments does not make that clear) - we should clarify what properties we want from privacy. |
This comment has been minimized.
This comment has been minimized.
|
From my typeck POV, the NPIP/RFC136 rule feels to me rather lintish - it is not sure exactly what it is trying to prevent. Local reasoning on reachability is always kind of odd - you need to be sure nobody exposes your API in some indirect way - but having some block on direct uses would be fine. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Yes I've read it. |
This comment has been minimized.
This comment has been minimized.
|
It seems somewhat unfortunate that What happens if the restriction is to a subpath? e.g. is the call to pub(module) fn foo() {}
fn bar() {
foo() // is foo visible here?
}
mod module {} |
sfackler
referenced this pull request
Dec 21, 2015
Merged
Implement RFC 1328 Custom Panic Handlers #30485
This comment has been minimized.
This comment has been minimized.
Hmm, you're right; if I'm going to allow
See the unresolved question section on this topic. |
This comment has been minimized.
This comment has been minimized.
In addition to user-oriented properties, I'd like to have the next guarantee: Update: Ideally this should be done based on reachability and not |
This comment has been minimized.
This comment has been minimized.
diwic
commented
Dec 22, 2015
|
There is no example with struct impls, but I assume they are covered as well? I've hit this in my bindings a few times, I wanted to do:
Now I'm instead doing this workaround:
Edit: Changed |
This comment has been minimized.
This comment has been minimized.
? |
This comment has been minimized.
This comment has been minimized.
diwic
commented
Dec 23, 2015
|
@petrochenkov - that doesn't work because
...could work, but it leaks the internal layout of |
This comment has been minimized.
This comment has been minimized.
|
Huge I'm very glad and grateful you came up with this @pnkfelix . I've run into situations where this would be very useful and much more straightforward than the contortions that are required today, but I had this (what I hope to be mis)conception that changes to item visibility rules/functionality would be very difficult to convince the team about. Glad it's happening from the inside! |
mdinger
reviewed
Dec 24, 2015
| fn semisecret(x: i32) -> i32 { use self::b::c::J; x + J } | ||
| pub fn foo(y: i32) -> i32 { semisecret(I) + y } | ||
| pub fn bar(z: i32) -> i32 { semisecret(I) * z } |
This comment has been minimized.
This comment has been minimized.
mdinger
Dec 24, 2015
Contributor
Comment at the top says I and foo are exported. Not sure why bar is also exported.
This comment has been minimized.
This comment has been minimized.
pnkfelix
Dec 24, 2015
Author
Member
i added fn bar to the example later (just so "many places" that semisecret would be called did actually mean "more than one place"), but forgot to update the comment above the mod a.
mdinger
reviewed
Dec 24, 2015
| use self::b::semisecret; | ||
| pub fn foo(y: i32) -> i32 { semisecret(I) + y } | ||
| pub fn bar(z: i32) -> i32 { semisecret(I) * z } |
This comment has been minimized.
This comment has been minimized.
mdinger
reviewed
Dec 24, 2015
|
|
||
| One can use these `pub(restriction)` forms anywhere that one can | ||
| currently use `pub`. In particular, one can use them on item | ||
| defintions, methods in an impl, the fields of a struct |
This comment has been minimized.
This comment has been minimized.
mdinger
reviewed
Dec 24, 2015
| use self::b::semisecret; | ||
| pub fn foo(y: i32) -> i32 { semisecret(I) + y } | ||
| pub fn bar(z: i32) -> i32 { semisecret(I) * z } |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
to describe a crate-scoped-item:
|
This comment has been minimized.
This comment has been minimized.
nixpulvis
commented
Dec 26, 2015
|
I was giving something along the lines of |
This comment has been minimized.
This comment has been minimized.
Did we ever clarify this in particular? Longer term, I would expect glob re-exports to re-export all things that are visible to the "re-exporter" (with the same privacy). However, our current rules about shadowing make it a problematic breaking change to add these semantics, because
But I should go make sure I'm caught up on this thread... |
This comment has been minimized.
This comment has been minimized.
nodakai
commented
Mar 13, 2016
|
What happens if we want to expose a name to multiple modules? |
petrochenkov
reviewed
Mar 13, 2016
|
|
||
| If a re-export occurs within a non-`pub` module, can we treat it as | ||
| implicitly satisfying a restriction to `super` imposed by the item it | ||
| is re-exporting? |
This comment has been minimized.
This comment has been minimized.
petrochenkov
Mar 13, 2016
Contributor
I'd prefer to start with the strict rules (i.e. the answer "No"). They fit better into the whole picture and can always be relaxed if necessary (I doubt it will be necessary).
aturon
removed
the
I-nominated
label
Mar 14, 2016
This comment has been minimized.
This comment has been minimized.
|
Huzzah! The @rust-lang/lang team has decided to accept this RFC. With respect to unresolved questions -- such as the strictness of certain rules -- I think we tend towards the stricter interpretation, but also intend to answer such questions after gaining some experience with an implementation. |
This comment has been minimized.
This comment has been minimized.
|
Tracking issue: rust-lang/rust#32409 |
This comment has been minimized.
This comment has been minimized.
|
@pnkfelix I think you still had some minor clarifications that you planned to make? |
jonas-schievink
referenced this pull request
Mar 21, 2016
Closed
Tracking issue for `pub(restricted)` privacy (RFC #1422) #32409
This comment has been minimized.
This comment has been minimized.
Welp. This has been sitting in my notifications for so long that I never noticed the cc. Anyway:
|
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis I'll try to update doc today |
pnkfelix
added some commits
Mar 22, 2016
pnkfelix
merged commit 51daa98
into
rust-lang:master
Mar 22, 2016
petrochenkov
referenced this pull request
Apr 3, 2016
Closed
Superfluous error message for a private `pub use` #32708
This comment has been minimized.
This comment has been minimized.
mitchmindtree
commented
Apr 6, 2016
|
An alternative idea for the syntax:
This syntax might be more intuitively associable with paths than the proposed syntax? |
jseyfried
referenced this pull request
Apr 11, 2016
Merged
Implement `pub(restricted)` privacy (RFC 1422) #32875
This comment has been minimized.
This comment has been minimized.
Xion
commented
Apr 29, 2016
|
I know I'm late to the party, but I just read this RFC and noticed the section where the author isn't sure about precedents to the suggested solution. The visibility system in Bazel (the build system) is basically identical to the this |
petrochenkov
referenced this pull request
Jun 28, 2016
Open
Tracking issue for `private_in_public` compatibility lint. #34537
petrochenkov
referenced this pull request
Jul 12, 2016
Closed
Semantic "private in public" enforcement. #1671
This comment has been minimized.
This comment has been minimized.
iqualfragile
commented
Mar 17, 2017
|
nomenclature idea: lets make "pub" be short for publish, if you don't specify where you publish it to everywhere, when you restrict it then you just publish your function/struct/member to them. |
pnkfelix commentedDec 21, 2015
Summary
Expand the current
pub/non-pubcategorization of items with the ability to say "make this item visible solely to a (named) module tree."The current
crateis one such tree, and would be expressed via:pub(crate) item. Other trees can be denoted via a path employed in ausestatement, e.g.pub(a::b) item, orpub(super) item.(accepted) RFC text
rendered draft