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 upType alias can be used to bypass privacy check #28450
Comments
This comment has been minimized.
This comment has been minimized.
|
triage: I-nominated cc @nrc, @rust-lang/lang |
rust-highfive
added
the
I-nominated
label
Sep 17, 2015
alexcrichton
added
the
T-lang
label
Sep 17, 2015
This comment has been minimized.
This comment has been minimized.
|
The workings around this were always a little subtle to me, so I'm not 100% sure if this is working as intended or just a bug where we didn't follow a Note that a fix for this (if we want one) is likely to have a lot of fallout so we'd definitely want to run it through crater to select a mitigation strategy. |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
I think this (that a type alias can increase visibility) is a feature, not a bug. The fact that we can re-export functions without re-exporting all the types they refer to is unfortunate, but kind of intentional. The last time this kind of thing was discussed, we decided that we would not try to be complete in the checking of private types in public signatures, since it is way too complex and we'd only try to enforce a syntactic distinction, rather than taking reachability, etc. into account. |
This comment has been minimized.
This comment has been minimized.
|
This does not, in fact, offer any real protection: trait Pointer { type Pointee; }
impl<T:?Sized> Pointer for *const T { type Pointee = T; }
type __CFArray = <CFArrayRef as Pointer>::Pointee; |
This comment has been minimized.
This comment has been minimized.
|
@nrc yeah that was my vague recollection as well, but I thought the rule we were going for was "if this isn't |
This comment has been minimized.
This comment has been minimized.
|
I would expect a |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
thematically related to #28325, at least |
This comment has been minimized.
This comment has been minimized.
|
triage: P-high -- backwards compat |
rust-highfive
added
P-high
and removed
I-nominated
labels
Sep 17, 2015
nikomatsakis
assigned
nrc
Sep 17, 2015
This comment has been minimized.
This comment has been minimized.
|
This is trivial to fix in some sense... but the usage of a type alias isn't really integral to the original testcase. Consider: #![crate_type="lib"]
mod b {
mod a {
pub struct S1;
pub struct S2(pub S1);
}
pub use self::a::S2;
}
pub fn g(s : b::S2) {
let s = s.0; // Oops, I can't name the type of the field.
} |
This comment has been minimized.
This comment has been minimized.
|
@eefriedman that is ok, because the struct was declared On Thu, Sep 17, 2015 at 7:51 PM, eefriedman notifications@github.com
|
aturon
assigned
aturon
and unassigned
nrc
Oct 8, 2015
This comment has been minimized.
This comment has been minimized.
|
I'm curious whether we expect the following to be allowed: type Foo = u8;
pub fn foo(f: Foo) {}That is, if you use a private type alias to reference a public type in a signature -- is that OK? Currently the snippet fails to compile. Fixing the original issue turns up some cases within |
This comment has been minimized.
This comment has been minimized.
|
@aturon
However, (I'm currently rewriting all this, I've finished |
This comment has been minimized.
This comment has been minimized.
|
Another very simpe hole in
|
This comment has been minimized.
This comment has been minimized.
|
@petrochenkov OK, thanks for the heads up that you're doing a rewrite. I was going to look at a couple issues in this vicinity as well, but maybe you can factor them in: The current goal is to get all of this checking in line with the relevant RFC. We may want to loosen some of the rules, eventually, but for now we should hew toward the conservative spec. The fundamental guarantee in the spec is that a type definition may only escape a module if it is marked I definitely agree that |
This comment has been minimized.
This comment has been minimized.
I'm not so sure. Here's a few examples: type Foo = Arc<Mutex<io::Read + Send + 'static>>;
pub fn foo(x: Foo) {}In this example, I've found myself wanting to use a pub use self::inner::Foo;
pub type Bar = self::inner::Bar;
mod inner {
struct Foo;
struct Bar;
}In this example, I feel that the re-export should be valid, but the I would expect Any desire to use |
This comment has been minimized.
This comment has been minimized.
|
@seanmonstar |
This comment has been minimized.
This comment has been minimized.
|
@seanmonstar
without allowing users to change the parameters by themselves. |
This comment has been minimized.
This comment has been minimized.
I don't think this is a hole. Rather, I think it is legal to (I happen to think we should extend this system somewhat, probably by allowing you to limit pub declarations to some enclosing modules, but this is the system we have today.)
I don't understand this restriction, can you clarify what it is? I think probably both |
This comment has been minimized.
This comment has been minimized.
(Unless by hole you just meant that we get link time errors, in which case I agree there is some sort of bug with the linker's code that identifies reachable symbols.) |
This comment has been minimized.
This comment has been minimized.
|
In this example that you gave: pub use self::inner::Foo;
pub type Bar = self::inner::Bar;
mod inner {
struct Foo;
struct Bar;
}The current rules are that both are in error. This is because |
This comment has been minimized.
This comment has been minimized.
I expect this to be in an error, as it is today. I find this mildly annoying sometimes, but it makes sense, since type aliases appear in rustdoc and so forth. |
This comment has been minimized.
This comment has been minimized.
In this case
If |
This comment has been minimized.
This comment has been minimized.
|
Now I'm reading the older edition of https://github.com/rust-lang/rfcs/blob/master/text/0136-no-privates-in-public.md written by @glaebhoerl and I like it better than the current version. Basically, Edit: with "new edition" it will be pretty hard to reduce the surface area of produced object files. |
This comment has been minimized.
This comment has been minimized.
|
(FWIW I like my original idea better too ;) the problem was basically that I didn't manage to figure out the right way to think about and specify the semantics in time (the one I wrote in the RFC was pretty confused, as far as I remember) and no one else seemed interested in trying, so we ended up with this less-ambitious formulation.) |
This comment has been minimized.
This comment has been minimized.
|
To some extent, this is water under the bridge, at least until another RFC is written. However, the problem with the initial formulation, from my POV, is that, under that formulation, just looking at a declaration (say, of a struct) did not give you the full story of its scoping. The story is simpler today: if you see One flaw, though, is that the story of All that said, I think that evaluating the overall reachability of items (versus checking whether they obey the "no private things in public APIs" rule) seems to just be two distinct concepts, and we have to deal with that. (That is, I'm not sure that collapsing both into one visitor is a good direction, though clearly they share some common code -- probably the bit that computes the successors to a given node in the reachability graph.) Evaluating the reachable set seems, however, to be a fairly straightforward process: it's just a DFS over the reachability graph, stopping at private edges, right? |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis woops, I forgot to make the 2 internal structs public. // these do the same thing, and compile today
pub use self::internal::Foo;
pub type Bar = self::internal::Bar;
mod internal {
pub struct Foo;
pub struct Bar;
}I was suggesting that the privacy visitor should assume the type alias is a wrapper struct with a public type: @petrochenkov Yes, being able to do that is excellent, and I didn't mean to take that away. However, I'd want it to be illegal if any of those slots used a private item. pub struct Foo;
struct Bar;
pub type MaybeFoo = Option<Foo>; // <-- cool
pub type MaybeBar = Option<Bar>; // <-- compiles today, but i think it shouldnt |
This comment has been minimized.
This comment has been minimized.
I see, this is a good motivation, @seanmonstar |
This comment has been minimized.
This comment has been minimized.
|
Thanks @petrochenkov. Do you mind if I re-assign this and the other privacy bugs to you, since I've halted work on them while you work on your rewrite? |
This comment has been minimized.
This comment has been minimized.
|
@aturon |
jethrogb
referenced this issue
Nov 7, 2015
Closed
Non-exported type in exported type signature does not error #29668
aturon
assigned
aturon
and unassigned
aturon
Nov 9, 2015
This comment has been minimized.
This comment has been minimized.
|
Prohibiting non- Also, strictly speaking, almost everything involving public traits should be |
seanmonstar commentedSep 16, 2015
The function
publicis exported, accepting the typePriv, even thoughPrivis not exported.