WEP: Re-export Syntax (pub use)
Context
Wado needs a way to re-export symbols from other modules. This is a common pattern in module systems where a library wants to expose items from its dependencies or internal modules as part of its public API.
Terminology
Wado distinguishes between two kinds of "public":
| Keyword | Term | Meaning |
|---|---|---|
pub |
module public | Visible to other Wado modules that import this module |
export |
world export | Exposed at the Component Model boundary (WASI world conformance) |
The pub use syntax combines module public visibility with import, creating a re-export.
Motivation
Without re-export, users must import from the original source:
// math/internal/trig.wado
pub fn sin(x: f64) -> f64 { ... }
pub fn cos(x: f64) -> f64 { ... }
// math/internal/exp.wado
pub fn exp(x: f64) -> f64 { ... }
pub fn log(x: f64) -> f64 { ... }
// User must know internal structure
use {sin, cos} from "math/internal/trig.wado";
use {exp, log} from "math/internal/exp.wado";
With re-export, the library can provide a unified API:
// math/mod.wado
pub use {sin, cos} from "./internal/trig.wado";
pub use {exp, log} from "./internal/exp.wado";
// User imports from the public API
use {sin, cos, exp, log} from "math";
Decision
Syntax
Re-export uses pub use followed by the standard import syntax:
// Re-export specific items
pub use {foo, bar} from "./internal.wado";
// Re-export with rename
pub use {internal_name as public_name} from "./internal.wado";
// Re-export from core/wasi modules
pub use {Option, Result} from "core:prelude";
pub use {Stdout} from "wasi:cli";
Semantics
pub usemakes imported symbols available to modules that import this module- The re-exported symbol behaves identically to the original
- Re-exports are resolved at compile time (no runtime cost)
- Circular re-exports are prohibited
Visibility Levels
| Declaration | Within module | Other Wado modules | CM world boundary |
|---|---|---|---|
fn foo() |
Yes | No | No |
pub fn foo() |
Yes | Yes | No |
export fn foo() |
Yes | Yes | Yes |
use {x} from "..." |
Yes | No | - |
pub use {x} from "..." |
Yes | Yes | - |
Restrictions
- A re-export names only an item the module can import, and gives it no more reach than the item has.
export useis a compile error. A re-export stays at module level and never reaches the CM boundary.- A namespace cannot be re-exported, so
pub use utils from …andinternal use utils from …are compile errors.use utils from "./utils.wado"names a module, not an item. Re-export the members by name instead:pub use { helper } from "./utils.wado". - A wildcard cannot be re-exported, so
pub use _ from …andinternal use _ from …are compile errors.use _ frombinds no name.
Consequences
Positive
- Libraries can organize code internally while presenting a clean public API
- Refactoring internal module structure doesn't break users
- Enables facade pattern for complex libraries
- Consistent with Rust's
pub usesemantics
Negative
- Adds complexity to the module system
- Symbol resolution must track re-export chains
- Error messages must show both original and re-export locations
Implementation Notes
- Parser: Extend
usestatement to accept optionalpubprefix - Symbol table: Track re-export relationships
- Name resolution: Follow re-export chains during lookup
- Error reporting: Include re-export path in "symbol not found" errors
Implementation Status
Implemented. Key components:
ReExportTargetstruct insymbol.rstracks re-export relationshipsregister_reexport()registers re-exports without creating duplicate symbolslookup_in_module()resolves re-export chains transparently- Circular re-export detection via visited set
First use case: i128/u128 types are defined in core:prelude/int128 and re-exported from core:prelude.
