Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Rust allow public access to a private module?

I am a newbie in Rust and just started to read the programming book while doing rustling exercises. In the modules2.rs exercise, I am confused why the following code compiles:

mod delicious_snacks {
    pub use self::fruits::PEAR as fruit;
    pub use self::veggies::CUCUMBER as veggie;

    mod fruits {
        pub const PEAR: &'static str = "Pear";
        pub const APPLE: &'static str = "Apple";
    }

    mod veggies {
        pub const CUCUMBER: &'static str = "Cucumber";
        pub const CARROT: &'static str = "Carrot";
    }
}

fn main() {
    println!(
        "favorite snacks: {} and {}",
        delicious_snacks::fruit,
        delicious_snacks::veggie
    );
}  

Specifically, I am wondering why it is OK for main to access private fruits and veggies modules just because their uses are marked pub? On the other hand, if we don't use pub use, then, without making fruits and veggies pub, one cannot access e.g., delicious_snacks::fruits::PEAR in main because fruits is not public. Similarly, if we don't use pub for const PEAR, even with pub use self::fruits::PEAR as fruit, we still cannot compile delicious_snacks::fruit. So what exactly is the rule here? Why is it OK to not mark pub for those modules?

like image 462
vanbastelaer Avatar asked Sep 20 '25 03:09

vanbastelaer


1 Answers

The constants PEAR/APPLE/CUCUMBER/CARROT are marked as pub, which means they can be accessed from everywhere, even if they're in a private module.

This is a common technique, to implement something in a private module, and re-export only the things we want, e.g.

// actual implementation is here
mod foo_internal;

pub use foo_internal::{Foo, Bar};

This still maintains privacy/visibility, since Foo and Bar can't be re-exported if they're private.

You can also create a new module hierarchy for users of your library:

mod foo_internal;

pub mod foo {
    pub use foo_internal::Foo;
}

pub mod bar {
    pub use foo_internal::Bar;
}

This clearly separates the public interface from implementation details, so the implementation can be freely refactored without changing the public modules.

like image 158
Aloso Avatar answered Sep 23 '25 07:09

Aloso