(rust book chapt. 7) experimental module structure does not compile

Hello,

I am working through the book and made a project "backyard" with structure outlined below. On "cargo build" I get 2 errors: in the "main.rs" file it says that garden is defined twice -

`garden` is defined multiple times
 --> src/main.rs:3:1
  |
1 | use crate::garden;
  |     ------------- previous import of the module `garden` here
2 |
3 | pub mod garden;
  | ^^^^^^^^^^^^^^^ `garden` redefined here` 

and that the function in_garden() cannot be found. I read the book and it says that if you have a "lib.rs" file in src and declare a module " mod garden;" the compiler will look in 3 directories - one of which is "src/garden/mod.rs". I also do not understand why the path is crate::garden::garden::in_garden(); as I pretty much just copied whats written in the book. Can someone explain why this fails? Thanks!

error[E0425]: cannot find function `in_garden` in module `garden`
 --> src/main.rs:6:13
  |
6 |     garden::in_garden();
  |             ^^^^^^^^^ not found in `garden`
note: function `crate::garden::garden::in_garden` exists but is inaccessible
 --> src/garden/mod.rs:2:2
  |
2 |     pub fn in_garden(){
  |     ^^^^^^^^^^^^^^^^^^ not accessible
backyard
--Cargo.lock
--Cargo.toml
--src
----main.rs
----garden
----lib.rs
------mod.rs
// backyard/src/garden/mod.rs
mod garden {
	pub fn in_garden(){
		println!("function from garden module.");
	}
}
// backyard/src/main.rs
use crate::garden;

pub mod garden;

pub fn main() {
    garden::in_garden();
}
// src/lib.rs
mod garden;

A mod statement with a semicolon is equivalent to a mod statement where you paste the contents of the file inside the block. So your code is equivalent to this:

// backyard/src/main.rs
use crate::garden;

pub mod garden {
    mod garden {
        pub fn in_garden(){
            println!("function from garden module.");
        }
    }
}

pub fn main() {
    garden::in_garden();
}
// src/lib.rs
mod garden {
    mod garden {
        pub fn in_garden(){
            println!("function from garden module.");
        }
    }
}

Two things to notice here:

  1. By mentioning garden.rs with a mod statement twice (in both lib.rs and main.rs), you are creating two copies of the module. The function may be unused in one copy even if you use the version in the other copy.
  2. By putting a mod garden block inside garden.rs, you are actually creating two levels of modules, so you have crate::garden::garden::in_garden instead of just crate::garden::in_garden.

Here's what I recommend:

// backyard/src/garden/mod.rs
pub fn in_garden(){
    println!("function from garden module.");
}
// backyard/src/main.rs
use backyard::garden;

pub fn main() {
    garden::in_garden();
}
// src/lib.rs
pub mod garden;

The thing to understand here is that lib.rs and main.rs are the roots of two different crates. One is called the library, and the other is the binary. The binary crate has a dependency on the library crate, and can access it using the name from your Cargo.toml (in this case backyard). You access the current crate with crate::, so if you wanted to access in_garden from within lib.rs, you would say crate::garden::in_garden instead.

To summarize:

  • To access things defined in the binary crate from the binary crate, use crate::.
  • To access things defined in the library crate from the library crate, use crate::.
  • To access things defined in the library crate from the binary crate, use backyard::.
  • You can't access things defined in the binary crate from the library crate.

Note also that it's possible to have multiple binary crates. If you make a backyard/src/bin directory, then each file will be a separate binary crate. Similarly, files in backyard/examples or backyard/tests are also compiled as separate crates. All of these crates can access the library crate, but none of them can access each other.

Additionally, note that you could also put pub mod garden in your main.rs file. This makes garden.rs part of the binary crate instead, and you would no longer be able to access it from the library crate, or from examples, or from tests.

2 Likes

thanks a lot for your thorough explanation! :slight_smile: