Modules and Visibility

Nested Modules

A nested module is a mod declared inside another mod, forming a multi-level hierarchy in the crate's module tree—either inline within a single source file or across nested subdirectories on disk.

Inline Nested Modules vs. File-Backed Nested Modules

Both inline nested mod blocks and directory-backed mod files produce the exact same logical module tree and obey the exact same visibility rules:

Inline Nested Modules (Single File):         File-Backed Nested Modules (`src/`):

  mod cloud {                                  src/
      pub mod storage {                        ├── main.rs          (`mod cloud;`)
          pub mod s3 {                         ├── cloud.rs         (`pub mod storage;`)
              pub fn upload() {}               └── cloud/
          }                                        ├── storage.rs   (`pub mod s3;`)
      }                                            └── storage/
  }                                                    └── s3.rs    (`pub fn upload() {}`)

Visibility Rules Across Nested Modules

  1. Top-down reachability requires every intermediate module to be visible: For code outside cloud to call cloud::storage::s3::upload(), storage, s3, and upload must all be marked pub (or re-exported via pub use).
  2. Bottom-up access to private ancestors is automatic: Code inside cloud::storage::s3 can access private items in cloud::storage, cloud, and the crate root without any pub annotations on those ancestor items.
mod cloud {
    // Private constant in `cloud`: visible to all nested descendants (`storage` and `s3`)
    const REGION: &str = "ap-southeast-1";

    pub mod storage {
        const BUCKET_PREFIX: &str = "prod";

        pub mod s3 {
            pub fn object_uri(key: &str) -> String {
                // Access private constants from both parent (`storage`) and grandparent (`cloud`):
                let region = super::super::REGION;
                let prefix = super::BUCKET_PREFIX;
                format!("s3://{prefix}-{region}/{key}")
            }
        }
    }
}

fn main() {
    let uri = cloud::storage::s3::object_uri("snapshots/2026-10-22.tar.zst");
    println!("Target URI: {uri}");
}
Target URI: s3://prod-ap-southeast-1/snapshots/2026-10-22.tar.zst

Error When an Intermediate Nested Module Is Private (E0603)

If a nested function s3::upload() is marked pub, but its parent module mod s3 is left private, callers outside storage cannot traverse through s3:

// ❌ does not compile
mod cloud {
    pub mod storage {
        mod s3 {
            pub fn upload() {}
        }
    }
}

fn main() {
    cloud::storage::s3::upload();
}
error[E0603]: module `s3` is private
  --> src/main.rs:10:21
   |
10 |     cloud::storage::s3::upload();
   |                     ^^  ------ function `upload` is not publicly re-exported
   |                     |
   |                     private module
   |
note: the module `s3` is defined here
  --> src/main.rs:3:9
   |
3  |         mod s3 {
   |         ^^^^^^

To allow callers to invoke upload() without making mod s3 public, either mark pub mod s3 or add pub use self::s3::upload; inside pub mod storage.