Visibility
This section specifies the pub visibility modifier and the intra-directory visibility rule: visibility boundaries in Rue are directories, not files.
A top-level function, struct, enum, or constant MAY be marked with the pub modifier. An item without pub is private.
A private item is visible throughout the directory that contains its defining file: code in any source file in the same directory may access it, including through a module import.
It is a compile-time error to access a private item through a module from a source file in a different directory than the item's defining file (error E0706).
A pub item is accessible through a module import from any directory.
A directory module's facade file lives inside the directory it fronts (10.1:3); the facade therefore has intra-directory access to the private items of the other files in that directory, while external importers of the directory module see only the facade's pub members.
// utils/_utils.rue — the facade
const strings = @import("strings");
pub fn format() -> i32 { strings.internal_format() } // OK: same directory
// utils/strings.rue
fn internal_format() -> i32 { 42 } // private
// main.rue — a different directory
fn main() -> i32 {
let utils = @import("utils");
utils.format() // OK: `format` is pub
// utils.internal_format() // would be an error even if imported:
// // private to the utils/ directory
}
Visibility is uniform across every multi-file compilation and every item kind: an item is usable outside its defining directory if and only if it is pub, whether its defining file was loaded via @import or listed explicitly in the compilation. Access to a private item through a module binding from another directory is error E0706 (10.4:18) — this is the diagnostic for privacy violations, since cross-module references are spelled through module bindings. Where an implementation still accepts an unqualified reference that names a cross-directory item directly (legacy forms removed with flat mode, ADR-0046), referencing a private item that way is error E0460.
Unqualified references resolve module-locally: a top-level name refers to an item of the referencing file (or a compiler builtin). A name defined only in other loaded files — imported or explicitly listed, pub or not, any directory — does not resolve unqualified; the reference is a name-resolution error (E0201 for variables/constants and enum type names in expressions, E0202 for functions, E0204 for types), never a silent resolution into another file. Cross-module access is spelled through a module binding (10.4:1).
// sub/lib.rue
fn secret() -> i32 { 99 } // private to sub/
pub fn open() -> i32 { 7 }
struct Hidden { n: i32, } // private to sub/
pub struct Shared { n: i32, }
pub const MAX: i32 = 16;
// main.rue — a different directory
const lib = @import("sub/lib");
fn main() -> i32 {
// secret() // error E0202: does not resolve here (10.3:8)
// Shared { n: 1 }; // error E0204: pub, but still module-scoped
// lib.secret() // error E0706: private to sub/ (10.4:18)
// lib.Hidden { n: 1 }; // error E0706: private to sub/
let s = lib.Shared { n: lib.MAX }; // OK: pub members through the binding
lib.open() + s.n // 7 + 16 = 23
}