-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Refine the story of externally referenced private structures. #10573
Comments
Is there any use case for them to be "yes"? i.e. is there ever a situation were one actually wants/needs to return a struct that is completely private (rather than just the fields)? I would think the most common time it occurs is accidentally, if one doesn't happen to have a test outside the module in which the struct is defined. (Of course, the complexity of making all-no work might be hard, e.g. |
On Tue, Nov 19, 2013 at 05:10:43PM -0800, Alex Crichton wrote:
Why do you say it's "too painful"? Is this such a common scenario? I don't have a strong opinion about this at the moment. It seems like |
This has been currently uncovered as part of the runtime's implementation. Inside of I'd imagine that @huonw's example of having a private structure in a public one might be common, but then again that's just conjecture. |
On Wed, Nov 20, 2013 at 10:47:58AM -0800, Alex Crichton wrote:
This seems to be an independent problem. Essentially we've |
Having a private structure as a private field inside of a public one is pretty common in my experience. |
@sfackler right but it's the opposite that we're discussing here, I think? that is, a private struct name with public fields. |
It is not clear what the implications are of sticking with our current rules. P-low. |
Perhaps related to http://www.researchgate.net/publication/221320580_Islands_Aliasing_Protection_in_Object-Oriented_Languages -- though I can't remember the details of what this paper involved :) |
In particular, my main worries, that I mentioned during triage, are:
Having said that: If we impose some additional small constraints, like "you cannot access members from a type that is priv to you", then I will probably be satisfied. |
We were thinking today that privacy is correct in denying access to the name of private types, but it may not be correct in denying access to the insides of private types. There are two remaining questions to me:
Privacy currently says yes to both of these questions, but it's very easy for privacy to say no. |
I'd personally say that it should just be illegal for private types to appear in such a way that means they're ever publically accessible, which would resolve both those questions, i.e. mod foo {
struct Private;
pub struct Public { not_priv: Private } // not ok
pub struct PrivField { priv not_not_priv: Private } // ok
fn private() -> Private {} // ok
pub fn public() -> Private {} // not ok
pub fn closure(_: |&Private| -> int) {} // not ok
} (I guess this would just involve checking that every type mentioned in a public function signature is accessible in the parent module.) |
We can also address the question another way:
Note though that even if you answer no to the above questions, |
Think I agree with @huonw. Just an outsider looking in, but it seems to me that the straightforward way to resolve this would be to go ahead and make the things illegal, and see if anything important breaks. It's easier to re-allow something later if there turns out to be a use case than the other way around. The one case I can think of offhand where you might want to have a private thing showing up in public API is to have a private super-trait of a public trait. This has the effect that other modules can use the trait, put it in their type signatures, and so forth, everything except make an |
I also agree with huonw. It seems a lot more straightforward to just remember that priv => those outside don't have to worry about it at all, and thus private items are solely implementation details of something. |
Since reader::vuint_at() returns a result of type reader::Res it makes sense to make it public. Due to rust's current behavior of externally referenced private structures, rust-lang#10573, you could still use the result and assign it to a variable if you let the compiler do the type assignment, but you could not explicitly annotate a variable to hold a reader::Res.
Another issue: can a public trait inherit from a private one? |
@cmr I would think yes; it'd be an entirely private implementation detail. Code that can't see the private trait just can't use it, which seems consistent to me. |
cc #11685 for an(other) example of a problem this would resolve (specifically, making it illegal to return private structures from public functions would make it impossible to compile that example). |
These are types that are in exported type signatures, but are not exported themselves, e.g. struct Foo { ... } pub fn bar() -> Foo { ... } will warn about the Foo. Such types are not listed in documentation, and cannot be named outside the crate in which they are declared, which is very user-unfriendly. cc rust-lang#10573
These are types that are in exported type signatures, but are not exported themselves, e.g. struct Foo { ... } pub fn bar() -> Foo { ... } will warn about the Foo. Such types are not listed in documentation, and cannot be named outside the crate in which they are declared, which is very user-unfriendly. cc rust-lang#10573
These are types that are in exported type signatures, but are not exported themselves, e.g. struct Foo { ... } pub fn bar() -> Foo { ... } will warn about the Foo. Such types are not listed in documentation, and cannot be named outside the crate in which they are declared, which is very user-unfriendly. cc #10573.
#12595 added a lint for non-exported types in exported type signatures (e.g. |
I'm going to close this now that rust-lang/rfcs#136 has been accepted. Our "refinement" was to disallow this pattern entirely. |
@alexcrichton Due to the subsequent rust-lang/rfcs#200 you can still formulate all of the original "problematic examples" as just "public type in private module" rather than "private type". E.g., where we had:
We can't write that any more, but we can still write:
|
Which can lead to linker errors as shown in this example (should look familiar!) |
@glaebhoerl yes, I consider that part of the "refinement" in that it's just our answer to the question. @japaric, indeed! I definitely consider that a compiler bug. |
@alexcrichton I don't understand - in particular what do you mean by "it" in "it's just our answer"? (My point was that all of the questions which used to exist (e.g. the ones listed in the OP) do still exist in some form.) |
"it" being "public means you're tagged with We've decided that you can still reference visibly private types and functions and such, but they must be declared as public. Anything preventing you from doing this (such as the compiler linkage errors) are just that, compiler bugs. |
Yes, that much is clear. What I mean to ask is: are the answers to questions 1-5 here, and any other similar questions, substituting "public type in private module" for "private type", all going to be "yes"? |
I think all 5 questions are answered by: If the struct is marked "pub", no, and if the struct is marked "pub", yes. If the struct itself is a private type (nor marked pub), then the answer is all no. |
…=Jarcho Ignore `file!()` macro in `print_literal`, `write_literal` changelog: [`print_literal`], [`write_literal`]: Ignore the `file!()` macro `file!()` expands to a string literal with its span set to that of the `file!()` callsite, but isn't marked as coming from an expansion. To fix this we make sure we actually find a string/char literal instead of assuming it's one and slicing It would also ignore any other macros that result in the same situation, but that shouldn't be common as `proc_macro::Span::call_site()` returns a span that is marked as from expansion Fixes rust-lang#10544
From my understanding, the story of a private structure that is returned from a public api is a little hazy today. For example, what's the reasonable thing to do in these situations:
Questions 1-4 are answered with 'yes' today, but the answer to question 5 is no. I believe that these should either all be no, or all be yes. In my opinion, it's just too painful for them to all be 'no', and it's unclear to me whether there's benefit to that.
Nominating, we need to decide this.
The text was updated successfully, but these errors were encountered: