Structs
Visibility of Fields and Methods
In Rust, every item, struct field, and method is private by default. Marking a struct as pub makes the type name visible outside its module, but its fields and methods remain private unless they are individually given a visibility modifier.
Visibility Modifiers on Structs, Fields, and Methods
| Modifier | Who Can Access the Item / Field / Method |
|---|---|
| (none — default) | Only the defining module and its descendant submodules |
pub(self) |
Identical to default private visibility (current module and descendants) |
pub(super) |
The immediate parent module and all of its descendants |
pub(in crate::path) |
The specified ancestor module crate::path and its descendants |
pub(crate) |
Any module anywhere inside the current crate, but hidden from external crates |
pub |
Publicly accessible to any module and (if the module path is exported) external crates |
Visibility Scopes Inside a Crate:
crate root (lib.rs) <-- `pub` (external) & `pub(crate)` (crate-wide)
└── mod network <-- `pub(in crate::network)`
└── mod connection <-- `pub(super)` (visible to `network`)
└── struct Socket <-- private (visible to `connection` + children)
└── mod tls <-- child modules can ALWAYS see parent's private items!
Struct Visibility vs. Field Visibility
A struct's fields can mix visibility levels freely:
mod catalog {
pub struct Product {
pub id: u64, // Public: anyone can read or write `product.id`
pub name: String, // Public: anyone can read or write `product.name`
pub(crate) sku: String, // Crate-visible: accessible anywhere in this crate
cost_cents: u64, // Private: accessible only inside `mod catalog`
}
impl Product {
// Public constructor required because `cost_cents` is private
pub fn new(id: u64, name: &str, sku: &str, cost_cents: u64) -> Self {
Self {
id,
name: String::from(name),
sku: String::from(sku),
cost_cents,
}
}
// Public method exposing a calculated value from the private field
pub fn retail_price_cents(&self) -> u64 {
self.cost_cents * 2
}
// Private helper method (omits `pub`)
fn validate_cost(&self) -> bool {
self.cost_cents > 0
}
pub fn is_valid(&self) -> bool {
self.validate_cost() && !self.name.is_empty()
}
}
}
fn main() {
let mut item = catalog::Product::new(10, "Mechanical Keyboard", "KB-87", 45_00);
// Public fields (`id`, `name`) and `pub(crate)` fields (`sku`) are accessible here:
item.name.push_str(" Pro");
println!(
"#{} {} (SKU: {}) -> Retail: {} cents (valid: {})",
item.id,
item.name,
item.sku,
item.retail_price_cents(),
item.is_valid()
);
}
#10 Mechanical Keyboard Pro (SKU: KB-87) -> Retail: 9000 cents (valid: true)
Compile Error When Accessing a Private Field or Method (E0616 / E0624)
Attempting to read a private field (item.cost_cents) or call a private method (item.validate_cost()) from outside the defining module produces a compile-time error:
// ❌ does not compile
mod vault {
pub struct Key {
secret: u64,
}
impl Key {
pub fn new(secret: u64) -> Self {
Self { secret }
}
fn raw_secret(&self) -> u64 {
self.secret
}
}
}
fn main() {
let k = vault::Key::new(999);
println!("{}", k.secret);
println!("{}", k.raw_secret());
}
error[E0616]: field `secret` of struct `vault::Key` is private
--> src/main.rs:19:22
|
19 | println!("{}", k.secret);
| ^^^^^^ private field
error[E0624]: method `raw_secret` is private
--> src/main.rs:20:22
|
11 | fn raw_secret(&self) -> u64 {
| --------------------------- private method defined here
...
20 | println!("{}", k.raw_secret());
| ^^^^^^^^^^ private method
Tuple Struct Field Visibility
Tuple struct fields (struct Pair(u32, u32);) are also private by default. Marking the struct pub struct Pair(u32, u32); exposes the type name Pair, while pub struct Pair(pub u32, pub u32); also makes the positional fields .0 and .1 and the tuple-struct constructor Pair(a, b) public.