Modules and Visibility

pub(in path)

The pub(in path) visibility modifier restricts an item, field, or method's visibility to a specific ancestor module identified by path (and all of that ancestor's descendant submodules).

Rules for the path in pub(in path)

  1. Must be an ancestor of the current module: You can only grant visibility to a module that encloses the current module (crate::..., super::..., or self). You cannot grant visibility exclusively to an unrelated sibling subtree without including the lowest common ancestor.
  2. In Rust 2018 and 2024 editions, path must start with crate::, super::, or self (for example, pub(in crate::network) or pub(in super::super)).
  3. pub(crate), pub(super), and pub(self) are shorthands:
    • pub(crate) is shorthand for pub(in crate).
    • pub(super) is shorthand for pub(in super).
    • pub(self) is shorthand for pub(in self) (identical to default private visibility).
Scoping Visibility to an Ancestor Subtree (`pub(in crate::http)`):

  crate
   ├── mod telemetry               <-- Outside `crate::http`: CANNOT access `parse_raw_frame`
   └── mod http                    <-- Target ancestor `crate::http`: CAN access
        ├── mod h2
        │    └── mod frame         <-- Defines `pub(in crate::http) fn parse_raw_frame()`
        └── mod client             <-- Inside `crate::http`: CAN access `parse_raw_frame()`

Sharing Deeply Nested Items Across a Subsystem (pub(in crate::...))

When an item is defined two or more levels deep inside a subsystem (crate::http::h2::frame), pub(super) only reaches crate::http::h2, whereas pub(crate) exposes it to the entire crate. Writing pub(in crate::http) scopes visibility to the exact crate::http subsystem:

mod http {
    pub mod h2 {
        pub mod frame {
            // Visible anywhere inside `crate::http` (including `http::client`),
            // but hidden from `main()` at the crate root:
            pub(in crate::http) fn encode_ping(id: u32) -> [u8; 4] {
                id.to_be_bytes()
            }
        }
    }

    pub mod client {
        pub fn send_ping(id: u32) -> [u8; 4] {
            // `http::client` is a descendant of `crate::http`, so it can call `encode_ping`:
            crate::http::h2::frame::encode_ping(id)
        }
    }
}

fn main() {
    let bytes = http::client::send_ping(0x0102_0304);
    println!("Encoded ping bytes: {bytes:02X?}");
}
Encoded ping bytes: [01, 02, 03, 04]

Error: Specifying a Non-Ancestor Module in pub(in path) (E0742)

Attempting to specify a sibling module that is not an ancestor of the defining module fails with compiler error E0742:

// ❌ does not compile
mod alpha {
    pub mod sub {}
}

mod beta {
    // Error: `crate::alpha` is not an ancestor of `mod beta`!
    pub(in crate::alpha) fn helper() {}
}

fn main() {}
error[E0742]: visibilities can only be restricted to ancestor modules
 --> src/main.rs:7:12
  |
7 |     pub(in crate::alpha) fn helper() {}
  |            ^^^^^^^^^^^^