Visibility and Privacy

In this chapter, we'll explore control access to code with pub and private visibility.

Visibility and Privacy

By default, items in Mana are private—they can only be accessed within the same module. Use pub to make items accessible from other modules.

Private by Default

module math
 
// Private - only accessible within this module
fn helper_function() -> int {
    return 42
}
 
// Public - accessible from other modules
pub fn add(a: int, b: int) -> int {
    return a + b + helper_function()  // Can use private helper
}

Making Items Public

Use pub before any declaration:

module shapes
 
// Public struct
pub struct Circle {
    pub radius: f32,    // Public field
    center_x: f32,      // Private field
    center_y: f32,      // Private field
}
 
// Public function
pub fn area(c: Circle) -> f32 {
    return 3.14159 * c.radius * c.radius
}
 
// Public constant
pub const PI: f64 = 3.14159265358979

Struct Field Visibility

Struct fields have their own visibility:

module user
 
pub struct User {
    pub name: string,      // Public - anyone can read
    pub email: string,     // Public
    password_hash: string, // Private - only this module
    internal_id: int,      // Private
}
 
impl User {
    // Public constructor - the only way to create a User
    pub fn new(name: string, email: string, password: string) -> User {
        return User {
            name: name,
            email: email,
            password_hash: hash(password),
            internal_id: generate_id(),
        }
    }
 
    // Public method
    pub fn display_name(self) -> string {
        return self.name
    }
 
    // Private helper
    fn hash(password: string) -> string {
        // Internal hashing logic
    }
}

Enum Visibility

When an enum is public, all its variants are public:

module status
 
pub enum Status {
    Active,
    Inactive,
    Pending,
}
 
// All variants (Active, Inactive, Pending) are accessible

Trait Visibility

module traits
 
pub trait Drawable {
    fn draw(self) -> void
    fn bounds(self) -> Rectangle
}
 
// Implementations inherit visibility from the trait
pub impl Drawable for Circle {
    fn draw(self) -> void {
        // ...
    }
 
    fn bounds(self) -> Rectangle {
        // ...
    }
}

Why Privacy Matters

Privacy helps you:

  • Hide implementation details — Change internals without breaking users
  • Enforce invariants — Control how data is modified
  • Create clean APIs — Expose only what's necessary
module counter
 
pub struct Counter {
    value: int,  // Private - can't be modified directly
}
 
impl Counter {
    pub fn new() -> Counter {
        return Counter { value: 0 }
    }
 
    pub fn increment(mut self) -> void {
        self.value = self.value + 1  // Controlled modification
    }
 
    pub fn get(self) -> int {
        return self.value  // Read-only access
    }
}

Continue to Imports and Paths.