Re-Exports with pub use
A pub use declaration (a re-export) brings an item into the current module's scope and simultaneously makes that item part of the current module's public interface, allowing callers to import or access it directly through the re-exporting module.
Why Re-Exports Matter: Decoupling Internal Layout from Public API
In a large library, internal code is often organized into deep, fine-grained submodules (crate::storage::btree::node::BTreeMap), whereas users of the library want a flat, ergonomic import path (my_crate::BTreeMap).
Even more importantly, if node is a private submodule (mod node), external callers cannot traverse my_crate::storage::btree::node::BTreeMap at all—unless a public ancestor module re-exports BTreeMap with pub use:
Internal Module Tree (For Maintainers): Public API Surface via `pub use` (For Users):
crate my_crate::Client
├── mod http (private!) my_crate::Request
│ ├── mod client -> pub struct Client my_crate::Error
│ └── mod request -> pub struct Request
└── mod error (private!)
└── pub enum Error
In `src/lib.rs`:
pub use crate::http::client::Client;
pub use crate::http::request::Request;
pub use crate::error::Error;
Flattening Deep Private Modules with pub use
mod internal_engine {
// Notice `lexer` and `parser` are PRIVATE modules (`mod`, not `pub mod`):
mod lexer {
#[derive(Debug)]
pub struct Token(pub &'static str);
}
mod parser {
use super::lexer::Token;
pub fn parse_first(input: &'static str) -> Token {
Token(input.split_whitespace().next().unwrap_or(""))
}
}
// Re-export `Token` and `parse_first` at the `internal_engine` level:
pub use self::lexer::Token;
pub use self::parser::parse_first;
}
fn main() {
// `main` cannot access `internal_engine::lexer::Token` because `mod lexer` is private,
// but CAN access it through the `pub use` re-export `internal_engine::Token`:
let tok: internal_engine::Token = internal_engine::parse_first("fn main() {}");
println!("Parsed token: {tok:?}");
}
Parsed token: Token("fn")
Building a Crate prelude Module with pub use
Many libraries define a pub mod prelude module that uses pub use to gather the crate's most commonly used traits and types in one place so users can write use my_crate::prelude::*;:
pub mod traits {
pub trait Summarize {
fn summary(&self) -> String;
}
}
pub mod models {
use crate::traits::Summarize;
pub struct Article {
pub title: String,
}
impl Summarize for Article {
fn summary(&self) -> String {
format!("[Article] {}", self.title)
}
}
}
pub mod prelude {
pub use crate::models::Article;
pub use crate::traits::Summarize as _;
}
fn main() {
use crate::prelude::*;
let item = Article {
title: String::from("Rust 2024 Edition Released"),
};
println!("{}", item.summary());
}
[Article] Rust 2024 Edition Released
Scoped Re-Exports (pub(crate) use and pub(super) use)
Re-exports can also use restricted visibility modifiers such as pub(crate) use or pub(super) use to flatten internal module paths for other modules within the same crate without exposing those items to external crates. Additionally, #[doc(inline)] or #[doc(no_inline)] can be placed on a pub use statement to control how rustdoc renders the re-exported item in generated documentation.