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 upAmend RFC 48 #200
Conversation
Gankro
reviewed
Aug 15, 2014
|
|
||
| * The trait being implemented is public. | ||
| * All input types (currently, the self type) of the impl are public. | ||
| * *Motivation:* If any of the input types or the trait is public, it |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
SiegeLord
commented
Aug 15, 2014
|
The pub use barrier::*;
mod barrier
{
pub struct A;
struct B;
} |
glaebhoerl
reviewed
Aug 15, 2014
|
|
||
| Note that the path to the public item does not have to be private. |
This comment has been minimized.
This comment has been minimized.
glaebhoerl
reviewed
Aug 15, 2014
| * *Motivation:* If any of the input types or the trait is public, it | ||
| should be impossible for an outside to access the items defined in | ||
| the impl. They cannot name the types nor they can get direct access | ||
| to a value of those types. |
This comment has been minimized.
This comment has been minimized.
glaebhoerl
Aug 15, 2014
Contributor
My thinking was that trait impls do not create items which can be referenced in APIs. You refer to the trait and its methods; these are then resolved during typechecking (not name resolution!) to a particular impl (if possible), but this happens behind the scenes and is opaque to the code doing the referencing. Is this point of view Haskell-centric and not true in Rust?
glaebhoerl
reviewed
Aug 15, 2014
| impl PubTrait<PrivStruct> for PubStruct { | ||
| // ^~~~~~~~~~ Error: Private type referenced from impl of | ||
| // public trait on a public type. [Note: this is | ||
| // an "associated type" here, not an input.] |
This comment has been minimized.
This comment has been minimized.
glaebhoerl
Aug 15, 2014
Contributor
This is... interesting. At first I was going to write:
For the same reason, it's not clear to me that this should be forbidden. Client code sees traits and their associated items; the typechecker sees the impls. Going with associated types syntax, client code can refer to the given type as fn some_func<T: PubTrait>(arg: T::AssocType); the fact that this may resolve to a private type doesn't seem significant, because it's abstract to some_func.
But, if you write fn other_func(arg: PubStruct::AssocType), that's no longer the case (this is very similar to pub type NotAssocType = PrivStruct). So I think you're in fact correct that this should be forbidden.
This comment has been minimized.
This comment has been minimized.
|
The reason I didn't (and still don't) think "is the item declared
If you can write this, then what have we actually gained? I suspect you could re-encode every otherwise forbidden example as public-thing-in-private-module this way. |
This comment has been minimized.
This comment has been minimized.
|
On Thu, Aug 14, 2014 at 06:51:37PM -0700, Gábor Lehel wrote:
I realize now that the threat model you are concerned about is I would like a guarantee that items declared as private are truly In contrast, I am not actually concerned about people inconsistently Basically the guarantee I want to achieve is:
I think this is a very pretty useful guarantee! When you think of |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis how would that rule interact with |
This comment has been minimized.
This comment has been minimized.
|
On Fri, Aug 15, 2014 at 12:40:14PM -0700, Steven Fackler wrote:
I think I spelled it out, but basically a |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis I can see how that guarantee would also be valuable. Wouldn't it make sense to extend it to encompass private modules as well, i.e. to be able to know for sure that anything in a private submodule is not leaked outside the parent module? That feels more "compositional" to me. There's basically two changes the amendment proposes:
Are these separable? Could we do 1. without 2.? That would provide all of the discussed guarantees. Are there any interesting/valuable module structures which would be ruled out? |
This comment has been minimized.
This comment has been minimized.
|
On Sun, Aug 17, 2014 at 11:42:45AM -0700, Gábor Lehel wrote:
I've been thinking about this off and on. You are addressing what was
Yes, they are separable, but as I wrote above I am still skeptical |
This comment has been minimized.
This comment has been minimized.
I'm not sure that this makes sense. I believe a module should be thought of as a self-contained unit, and that decisions about what to do with the items it exposes, including whether to expose them further, are the right and responsibility of the parent module, not the module itself. The way to say that the items in a I have a set of examples which I think should clearly delineate the things which should be rejected, as well as how to modify them to make them legal, and I believe that this is 'complete' and logically extends to cover all relevant cases in a way that maintains the desired guarantees. But I'm not yet sure of the best way to put the rules into words (and code). Here they are. I've omitted the obvious cases where everything is in the same module. Not OK:
OK:
Not OK:
OK:
Not OK:
OK:
In particular |
alexcrichton
assigned
nikomatsakis
Sep 4, 2014
alexcrichton
force-pushed the
rust-lang:master
branch
from
6357402
to
e0acdf4
Sep 11, 2014
aturon
force-pushed the
rust-lang:master
branch
from
4c0bebf
to
b1d1bfd
Sep 16, 2014
pcwalton
merged commit 3cd79b6
into
rust-lang:master
Sep 18, 2014
This comment has been minimized.
This comment has been minimized.
ben0x539
commented
Sep 25, 2014
|
so this pr turned an accepted rfc around, basically? |
This comment has been minimized.
This comment has been minimized.
|
@ben0x539 I'm not sure why the link wasn't included when this was merged, but this was discussed at a weekly meeting as with any RFC. |
This comment has been minimized.
This comment has been minimized.
ben0x539
commented
Sep 25, 2014
|
yeah, ok, but... at this point you might as well have retroactively rejected the old rfc, the current version shares neither the motivation nor the design with it and the changes don't really stem from discussion on the old rfc pr. |
alexcrichton
referenced this pull request
Oct 7, 2014
Closed
Can still publicly re-export traits that inherit from private supertraits #17847
glaebhoerl
referenced this pull request
Nov 2, 2014
Closed
Refine the story of externally referenced private structures. #10573
aturon
referenced this pull request
Nov 5, 2015
Closed
Type alias can be used to bypass privacy check #28450
SimonSapin
referenced this pull request
Jan 14, 2016
Closed
"error: private type in public interface" in private module #30905
This comment has been minimized.
This comment has been minimized.
|
Sorry I’m late to the party, but I don’t understand the motivation for this change. I find the previous reachability-based behavior to be superior, and don’t see a reason to prefer the current one. rust-lang/rust#30905 shows how the current behavior has both false positives and false negatives. |
This comment has been minimized.
This comment has been minimized.
|
The reason that I, at least, prefer the current setup is that I only have to look at the definition of an item to understand how widely it can be referenced. In particular, if it is private, then I know that it does not leak outside the current module (whereas, without any rules at all, I have to scan the signatures of public items to know that for sure). In the reachability-based variants, I have to scan and understand the That said, I agree that rust-lang/rust#30905 represents a real problem. I just disagree that reachability is the better fix. I personally would prefer a system like #1422, which allows us to directly specify publicity at a finer granularity. This way, your example from rust-lang/rust#30905 (actually, a slightly modified version): pub mod outer {
struct HostInternal;
mod parser {
use super::HostInternal;
pub fn parse() -> HostInternal {...}
}
}could be accommodated by modifying Historically, we settled on So perhaps the question then becomes whether you would be happy with the system proposed in #1422? |
This comment has been minimized.
This comment has been minimized.
|
By the way, there was some talks around 1.0 about keeping type ascribed source code on crates.io to avoid breakage from type inference changes. |
nikomatsakis commentedAug 15, 2014
The original definition of public items was based on reachability rather than simply checking whether the item is declared
pubor not. The RFC also did not describe how privacy andimpldefinitions are related.