Skip to content
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

pub use can reference private items in a an enclosing module #23266

Closed
nrc opened this issue Mar 10, 2015 · 14 comments
Closed

pub use can reference private items in a an enclosing module #23266

nrc opened this issue Mar 10, 2015 · 14 comments
Labels
A-visibility Area: Visibility / privacy.

Comments

@nrc
Copy link
Member

nrc commented Mar 10, 2015

pub use should not be able to make a private item public, e.g., this is illegal:

mod a {
    pub use self::b::Bar;  // error: type `Bar` is private

    mod b {
        struct Bar;
    }
}

However, if the private item is in an enclosing module then this is allowed. That is wrong (I think). However, it gets more complicated depending on if the enclosing module is itself public, because there is a useful pattern where the submodule pub uses an item in the enclosing module and that does not increase its visibility. Here are the possibilities:

mod a {
    struct Foo;

    mod b {
        pub use super::Foo; // ok - only already visible in a and sub-mods
    }
}

mod c {
    struct Foo;

    pub mod d {
        pub use super::Foo; // not ok - increases visibility to a sibling of c
    }
}

pub mod e {
    struct Foo;

    mod f {
        pub use super::Foo; // ok, but only if e does not pub use f
    }
}

pub mod g {
    struct Foo;

    pub mod h {
        pub use super::Foo;  // not ok, increases visibility to the whole world
    }
}

I'm not sure if we can check the third case easily (or at all). It might only be worth allowing the first case (this would break some code in the Rust repo and probably others though).

Note also that this interacts with the ban on private types in public items - this hole in visibility makes that work some times (I need to think more about that though)

@nrc nrc added the A-visibility Area: Visibility / privacy. label Mar 10, 2015
@nrc
Copy link
Member Author

nrc commented Mar 10, 2015

triage: I-nominated (1.0 beta)

back-compat issue

@rust-highfive rust-highfive added this to the 1.0 beta milestone Mar 10, 2015
@alexcrichton
Copy link
Member

Being able to access a parent's private items is an intentional part of the privacy system (you can access any private item in your ancestry). Although being able to reexport those private items may not necessarily be intended...

@nrc
Copy link
Member Author

nrc commented Mar 11, 2015

Yeah, the title is not very clear, sorry, but it is the re-export part that I think is the bug, not the access.

@nrc
Copy link
Member Author

nrc commented Mar 11, 2015

I think actually it is not as bad as I thought, in particular the third case is always Ok. Even if e does pub use f::Foo, then it is Ok, because Foo 'belongs' to e and e is still in control of its visibility.

So that suggests that a fairly simple rule is that it should only be allowed to pub use an enclosing module's private items from a private module.

@nrc
Copy link
Member Author

nrc commented Mar 11, 2015

Hmm, and now I'm not sure of the intended behaviour here. You can use pub use to expose a private item in your own module, so why not in an enclosing module? I don't think we prevent pub use anywhere more strongly than we prevent other access to private items.

@nrc nrc removed this from the 1.0 beta milestone Mar 11, 2015
@nrc
Copy link
Member Author

nrc commented Mar 11, 2015

Note that this issue is consistent with RFC 136 (i.e., under that RFC, the current implementation is wrong).

@pnkfelix
Copy link
Member

cc me

@nrc
Copy link
Member Author

nrc commented Mar 11, 2015

Note that currently you can pub use your own private members, that might be a bug too. E.g.,

pub mod a {
    pub use self::Priv as Pub;
    struct Priv;
}

pub fn main() {}

@nikomatsakis
Copy link
Contributor

I think that per RFC 136 a pub use should require that the referenced items be public.

@nikomatsakis
Copy link
Contributor

(Whether or not they are in your module, a parent's module, etc)

@nikomatsakis
Copy link
Contributor

At least that was the intended semantics.

@mahkoh
Copy link
Contributor

mahkoh commented Mar 12, 2015

I think that per RFC 136 a pub use should require that the referenced items be public.

Does that include the whole path? If so then that sounds wrong. Having to make every submodule you reexport an item from public makes it harder to hide the private interface.

@nrc
Copy link
Member Author

nrc commented Mar 12, 2015

@mahkoh No, it means literally just that the item must be public

@nrc
Copy link
Member Author

nrc commented Mar 12, 2015

I was thinking about cases with > 2 modules and I believe the rule that must hold is the same one I outline here. That is a pub use can only mention a private item if there is a private module between the item and the pub use.

In this case, there is also a simpler (and more conservative) model, which is that pub use can only mention public items.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-visibility Area: Visibility / privacy.
Projects
None yet
Development

No branches or pull requests

6 participants