Modules with multiple files

I'm trying to figure out how to use Rust's modules in separate files and I'm stuck. I'd like to know the proper way to have a module living in a separate file that is brought into scope and used in main.rs. Right now, the folder structure looks like this:

src
--main.rs
--user_input.rs

In user_input.rs I've attempted to do this:

pub mod user_input {
    pub use structopt::StructOpt;
   
    pub struct Cli {
      ...
    }

    pub fn get_user_input() {
        ...
    }

}

and then in main.rs I try to bring into scope:

mod user_input;

fn main() {
    user_input::get_user_input();
}

But it says it can't find get_user_input in the user_input module.

Also, what's the proper way to bring in an external crate within a module? Is the way I've done it with:

pub mod user_input {
    pub use structopt::StructOpt;
...

correct? Do I need pub in front of the use structopt?

Implicitly, the file user_input.rs already is the user_input module, so you only need to write

// pub mod user_input { // not needed !
pub use structopt::StructOpt;
   
pub struct Cli {
  ...
}

pub fn get_user_input() {
    ...
}
// }  // not needed !

in user_input.rs

3 Likes

user_input.rs should probably look like this (minus the indentation that’s hard to get rid of on mobile):

    use structopt::StructOpt;
   
    pub struct Cli {
      ...
    }

    pub fn get_user_input() {
        ...
    }

Every mod statement defines a new module, so your original code had a crate::user_input module (from the statement in main.rs) and a crate::user_input::user_input submodule (from the statement in user_input.rs.

You only need pub use ... if you want to make the imported item visible outside the module. That’s a relatively rare need, since any other module can import it from the external crate itself as well.

2 Likes

Oh, wow - I don't recall having seen that in Chapter 7 but that's great to know.

Thank you, I just noticed that as I was reading your response : ). However, I note that I can even remove pub from in front of struct Cli and it still works....? So the struct doesn't need to also be public in order for a public function to utilize it?

Yep ! Well, here note that main is not public :grin: But the following code would also compile:

pub fn exported_function() {
    let x: PrivateType = ...;
}

struct PrivateType {
    // ...
}

Here, any user of exported_function does not need to know about PrivateType: this is essentially an implementation detail.

1 Like

You never write mod twice for the same module or file. mod works the same as enum, struct, and fn — crates a new named item exactly where it is.

You wouldn't write struct Cli {} in every file you want it. You'd define it once, and then use it elsewhere. Same with mod user_input.

It's different from all other languages where similar constructs either mean "give me code from a file" or "I'm this module". In Rust it's neither of these.

2 Likes