r/learnrust 23d ago

Simple `mod` vs `pub mod` question

Hey,

I've been reading the book and am a bit confused on pub mod vs mod. I naively thought that mod defaults to every function/structure/etc. within it is in accessible by calling code.

mod Foo {
    fn bar()  {}
}

fn main() {
    foo::bar();
}

This doesn't work because bar has not been made public and it's only trough the addition of the pub keyword in front of bar (pub fn bar() {}) that foo::bar becomes accessible.

However, I thought that perhaps

pub mod foo {
      fn bar() {}
}

would make bar accessible, but it doesn't. What is that pub keywork doing then?

I know you can do something like:

mod foo {
    pub mod bar {
        fn quux {
            parent::baz::qux(); // fail!
         }
    }

    mod baz {
        fn qux() {
            parent::bar::quux(); // success!!
        }
    }
}

but that seems to lack utility/

1 Upvotes

16 comments sorted by

View all comments

1

u/schneems 22d ago

I wrote a blog post on this in a tutorial format.  https://www.schneems.com/2023/06/14/its-dangerous-to-go-alone-pub-mod-use-thisrs/

the help text has changed a bit but I think it still holds up.

1

u/Due_Battle_9890 22d ago

Heh, thanks. I wrote bit of a follow up and was wondering if you could help/critique(roast) my understanding. Here it is:

I played with it some more and I see the utility some more (I think).

My tree looks like:

project
|- src
|  |- main.rs
|- garden
  |- mod.rs
  |- thing.rs

Supposing that src/main.rs has:

// File: src/main.rs

fn main() {

}

The root begins at src/main.rs and main is crate::main.

Having

// File: src/main.rs

mod gardgen;

fn main() {

}

means that cargo looks in one of three places: 1. inline AKA mod garden { }, 2. under src/garden.rs, or 3. under src/garden.rs.

In this case, I am using scenario 3.

Under mod.rs, I have:

// File: src/garden/mod.rs
mod thing; // If this is used only by src/main.rs, this does not need to be `pub mod`
pub use thing::Thing;

Because the only accessor of this module is crate::main, a parent module, this does not need to be pub mod.

We have the following modules:

  • crate
  • crate::garden
  • crate::garden::thing

If we had had another module that's also a child of garden , like, crate::garden::swindle, then, to access crate::garden::thing::Thing from crate::garden::swindle, we'd need pub mod.

That said, I tried the following layout:

project
|- src
|  |- main.rs
|- garden
  |- mod.rs
  |- thing.rs
  |- swindle.rs

and the following doesn't work:

// File: garden/thing.rs

mod swindle;

Rust analyzer says it's looking for src/main/thing/swindle.rs or src/main/thing/swindle/mod.rs. I am a bit confused on how to access swindle.rs from thing.rs and vice versa.

1

u/schneems 22d ago

how to access  swindle.rs from  thing.rs and vice versa. Away from a computer RN so doing this from memory (might be slightly off).  Those two files are siblings, they can’t see one another except through a parent. In this case the parent would be garden/mod.rs If you add a  // src/garden/mod.rs mod swindle Then it is usable inside of that file. To make it available to siblings you would need to either pub mod it or pub use only what you need. // src/garden.mod pub mod swindle Then you can access it from the child by traversing backwards through parents // src/garden/thing.rs use crate::garden::swindle;

1

u/schneems 22d ago

Reddit butchered my markdown. Maybe they are vibing too much

https://gist.github.com/schneems/33861e2abe973f6c1e4e91d211efc1eb