Skip to content

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

Closed

Description

@nrc

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)

Activity

  1. nrc commented on Mar 10, 2015

    @nrc
    MemberAuthor

    triage: I-nominated (1.0 beta)

    back-compat issue

  2. added this to the 1.0 beta milestone on Mar 10, 2015
  3. alexcrichton commented on Mar 11, 2015

    @alexcrichton
    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...

  4. nrc commented on Mar 11, 2015

    @nrc
    MemberAuthor

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

  5. nrc commented on Mar 11, 2015

    @nrc
    MemberAuthor

    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.

  6. nrc commented on Mar 11, 2015

    @nrc
    MemberAuthor

    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.

  7. removed this from the 1.0 beta milestone on Mar 11, 2015
  8. nrc commented on Mar 11, 2015

    @nrc
    MemberAuthor

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

  9. pnkfelix commented on Mar 11, 2015

    @pnkfelix
    Contributor

    cc me

  10. nrc commented on Mar 11, 2015

    @nrc
    MemberAuthor

    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() {}
    
  11. nikomatsakis commented on Mar 11, 2015

    @nikomatsakis
    Contributor

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

  12. nikomatsakis commented on Mar 11, 2015

    @nikomatsakis
    Contributor

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

  13. nikomatsakis commented on Mar 11, 2015

    @nikomatsakis
    Contributor

    At least that was the intended semantics.

  14. mahkoh commented on Mar 12, 2015

    @mahkoh
    Contributor

    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.

  15. nrc commented on Mar 12, 2015

    @nrc
    MemberAuthor

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

  16. nrc commented on Mar 12, 2015

    @nrc
    MemberAuthor

    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.

  17. added a commit that references this issue on Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-visibilityArea: Visibility / privacy

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions