Search code examples
functionrustmoduledirectorysubdirectory

How do I import functions from subfolders in Rust


I have the main main.rs in the src folder. The main.rs contains the following content.

#[allow(dead_code)]
fn main() {
    println!("Hello, world!");
    hallo();
}

The main.rs in the src/lib folder does not currently have any content.

How can I now use the function "hello" from the test.rs in the main.rs in the src folder? The test.rs contains the following content.

fn hallo(){
    println!("hallo");
}

My folder structure looks like this.

|   Cargo.lock
|   Cargo.toml
|           
+---src
|   |   main.rs
|   |   
|   \---lib
|           main.rs
|           test.rs
```

Solution

  • This gets into the Rust module system. I'll try my best to explain it, but the Book does a much better job, so if you're confused, go ahead and check it out here. Basically, each file in Rust (besides main.rs or lib.rs) corresponds to one module in a crate (main.rs and lib.rs are the crate's root). Everything in that file is exposed under that module. To create a module, you add this line to its parent module (or to lib.rs or main.rs, which makes it a submodule under the crate):

    mod somemod;
    

    Then, you have two options:

    • Add a file called somemod.rs in the same folder as the file where you put that mod somemod; declaration. Your file structure would look like this:
    |
    +---main.rs
    +---somemod.rs
    
    • Add a folder called somemod in the same folder as the file with the mod somemod; declaration. This would be used if you wanted somemod to have child modules; you'd use the same two options to create child modules as you did to create the top-level one. Your file structure looks like this:
    |
    +---main.rs
    +---somemod
        |
        +---mod.rs
    

    Then, after that line (and before, if you really wanted), you'd be able to use the somemod namespace to refer to any public member of the somemod module:

    mod somemod;
    
    // later on ...
    somemod::foo();
    

    You could also use the use keyword to bring a member of somemod into the current namespace:

    mod somemod;
    use somemod::foo;
    
    // later on ...
    foo();
    

    So, in your case, your code would look like this:

    main.rs:

    mod test;
    use test::hallo;
    
    #[allow(dead_code)]
    fn main() {
        println!("Hello, world!");
        hallo();
    }
    

    test.rs:

    pub fn hallo() {
        println!("hallo");
    }
    

    Note that in order to be able to reference hallo from outside the module, we had to add the pub keyword in from of fn hallo.