293

By following this guide I created a Cargo project.

src/main.rs

fn main() {
    hello::print_hello();
}

mod hello {
    pub fn print_hello() {
        println!("Hello, world!");
    }
}

which I run using

cargo build && cargo run

and it compiles without errors. Now I'm trying to split the main module in two but cannot figure out how to include a module from another file.

My project tree looks like this

├── src
    ├── hello.rs
    └── main.rs

and the content of the files:

src/main.rs

use hello;

fn main() {
    hello::print_hello();
}

src/hello.rs

mod hello {
    pub fn print_hello() {
        println!("Hello, world!");
    }
}

When I compile it with cargo build I get

error[E0432]: unresolved import `hello`
 --> src/main.rs:1:5
  |
1 | use hello;
  |     ^^^^^ no `hello` external crate

I tried to follow the compiler's suggestions and modified main.rs to:

#![feature(globs)]

extern crate hello;

use hello::*;

fn main() {
    hello::print_hello();
}

But this still doesn't help much, now I get this:

error[E0463]: can't find crate for `hello`
 --> src/main.rs:3:1
  |
3 | extern crate hello;
  | ^^^^^^^^^^^^^^^^^^^ can't find crate

Is there a trivial example of how to include one module from the current project into the project's main file?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ave
  • 18,083
  • 9
  • 30
  • 39
  • 1
    possible duplicate of [Rust basic imports (includes)](http://stackoverflow.com/questions/26224947/rust-basic-imports-includes) – Levans Oct 15 '14 at 18:52
  • Related to http://stackoverflow.com/questions/22596920/split-a-module-across-several-files – Kelvin Jul 31 '15 at 15:50

6 Answers6

443

You don't need the mod hello in your hello.rs file. Code in any file but the crate root (main.rs for executables, lib.rs for libraries) is automatically namespaced in a module.

To include the code from hello.rs in your main.rs, use mod hello;. It gets expanded to the code that is in hello.rs (exactly as you had before). Your file structure continues the same, and your code needs to be slightly changed:

main.rs:

mod hello;

fn main() {
    hello::print_hello();
}

hello.rs:

pub fn print_hello() {
    println!("Hello, world!");
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Renato Zannon
  • 28,805
  • 6
  • 38
  • 42
  • 10
    Late Question wouldn't it also work if I specify it with use hello instead of mod hello?! – Christian Schmitt Sep 16 '15 at 17:23
  • 51
    @ChristianSchmitt No, they are different things. `use` is just a namespace thing, while `mod` pulls in the file. You would use `use`, for example, to be able to call the `print_hello` function without having to prefix with the namespace – Renato Zannon Sep 16 '15 at 19:08
92

If you wish to have nested modules...

Rust 2018

It's no longer required to have the file mod.rs (although it is still supported). The idiomatic alternative is to name the file the name of the module:

$ tree src
src
├── main.rs
├── my
│   ├── inaccessible.rs
│   └── nested.rs
└── my.rs

main.rs

mod my;

fn main() {
    my::function();
}

my.rs

pub mod nested; // if you need to include other modules

pub fn function() {
    println!("called `my::function()`");
}

Rust 2015

You need to put a mod.rs file inside your folder of the same name as your module. Rust by Example explains it better.

$ tree src
src
├── main.rs
└── my
    ├── inaccessible.rs
    ├── mod.rs
    └── nested.rs

main.rs

mod my;

fn main() {
    my::function();
}

mod.rs

pub mod nested; // if you need to include other modules

pub fn function() {
    println!("called `my::function()`");
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
amxa
  • 1,147
  • 9
  • 6
  • 12
    Suppose I wanted to use something from `inaccessible.rs` in `nested.rs`... how would I do that? – Heman Gandhi Jun 30 '19 at 20:00
  • 10
    To access a sibling .rs file from a file other than main.rs, use the path attribute. So, at the top of nested.rs, add the following: `#[path = "inaccessible.rs"]` and on the next line: `mod inaccessible;` – Gardener Jul 24 '19 at 11:26
  • @Gandhi See [The path attribute](https://doc.rust-lang.org/reference/items/modules.html) – Gardener Jul 24 '19 at 11:41
  • 3
    @HemanGandhi add `mod inaccessible;` to `my/mod.rs` to make it submodule of `my`, then access sibling module from `nested.rs` by relative path `super::inaccessible::function()`. you dont need `path` attribute here. – artin Nov 14 '19 at 15:59
  • I'm not sure the 2018 way of naming the file after the directory is more idiomatic. I for one prefer the old approach for a clean directory tree, and plenty of crates also follow it. – Chayim Friedman Jun 01 '22 at 04:30
  • Am I weird for thinking that the 2015 example makes more sense? – Charlie Jan 03 '23 at 18:48
  • Is there a way to avoid both `mod.rs` and also the extra top-level file, `my.rs`? – Daniel Waltrip Apr 19 '23 at 02:03
49

I really like Gardener's response. I've been using the suggestion for my module declarations.

./src
├── main.rs
├── other_utils
│   └── other_thing.rs
└── utils
    └── thing.rs

File main.rs

#[path = "utils/thing.rs"] mod thing;
#[path = "other_utils/other_thing.rs"] mod other_thing;

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

File utils/thing.rs

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

File other_utils/other_thing.rs

#[path = "../utils/thing.rs"] mod thing;

pub fn bar() {
  println!("bar");
  thing::foo();
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rodo
  • 734
  • 7
  • 6
  • 1
    Had to use this 'trick' to reexport `fn` with same name as the file it was in. `#[path = "./add_offer.rs"] mod _add_offer; pub use self::_add_offer::add_offer;` – Arek Bal May 04 '20 at 00:10
  • 9
    As a Rust newbie, it's a bit disturbing that such a simple concept (importing other bits of code) requires so much research. Plus the #[path..] syntax is ugly – NullPumpkinException Aug 06 '21 at 07:19
  • 6
    This is misleading, the `#[path = ...]` attribute should not be used except in obscure cases, and certainly not by newbies. Each time you do `mod thing`, it *creates a new module*, even if `#[path = ...]` makes them point to the same file. Meaning in this sample, there are two separate `thing` modules declared: `crate::thing` and `crate::other_thing::thing`. Its likely not an issue here since it only includes a function, but if you define types, it can lead to confusion when the compiler reports "expected mod1::A, found mod2::A". – kmdreko Aug 25 '21 at 21:21
  • 4
    Please use the standard mechanisms. If you really want this file structure without intermediate `mod.rs` files, you can declare them in `main.rs` like `mod other_utils { pub mod other_thing; }` and `mod utils { pub mod thing; }`. Then you can access them like `crate::other_utils::other_thing` and `crate::utils::thing`. – kmdreko Aug 25 '21 at 21:22
11

In a non main.rs (or lib.rs) file if you want to include from a file in the same directory then the code below works. The key is to use the word super:: for the include. (This is how I rewrote the answer of rodo without using path.)

Directory tree:

src
├── main.rs
├── my.rs
└── my
    ├── a.rs
    └── b.rs

To include a.rs in b.rs:

File src/my/a.rs

pub fn function() {
    println!("src/my/a.rs/function()");
}

File src/my/b.rs

use super::b::function;

fn f2() {
    function();
}

File src/my.rs

mod a;
mod b;

File src/main.rs

mod my;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
keiv.fly
  • 3,343
  • 4
  • 26
  • 45
6

As of 2022

├── src
├── main.rs
├── scripts
│   └── func.rs
└── scripts.rs

If I want to call the functions from the func.rs file (which are inside the scripts folder), I created a so-called "linking" file in the root directory the same as the folder's name (it's not necessary to have the linking file name and the folder name the same).

Content of file scripts/func.rs:

pub fn sayHello(){
    println!("Hello, World!");
}

In the scripts.rs file I have:

pub(crate) mod func;

Then in my main.rs file I have called the sayHello() function as below:

mod scripts;
fn main() {
    scripts::func::sayHello();
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Julfikar
  • 1,353
  • 2
  • 18
  • 35
  • 1
    Re *"As of 2022"*: Can you [state](https://stackoverflow.com/posts/71943939/edit) the version(s) of stuff (compilers, conventions, documents/specifications, etc.)? Perhaps also which system (incl. versions) this was tested on. (But ***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today.) – Peter Mortensen May 05 '22 at 21:41
1

There's sort of two cases to this question, and the answers I've seen so far only cover one case: when you have a main.rs, and a.rs, and a b.rs, all in the same directory, but you want to use functions from a.rs or b.rs in main.rs, but I haven't seen anyone cover the opposite case, so I'll do that here.

Given main.rs, a.rs, and b.rs all in the same directory, and you want to use functions from B in A, or B in A:

In main.rs

mod a;
mod b;

use crate::a::*;
use crate::b::*;

// To call a function from a.rs, do:
a::my_function_from_a();

In a.rs

use crate::b;

// To call a function from b.rs, do:
super::b::my_function_from_b();

The super keyword in a.rs is where the magic happens. Annoyingly, the behavior is different than the Ruby version of super.

If you don't use the super keyword you'll get the dreaded: [E0433] use of undeclared crate or module.

Raleigh L.
  • 599
  • 2
  • 13
  • 18