Everything in Rune has a unique name. Every function, type, and import. This name is what identifies that thing, and is called its item. Rune performs compile time checks to make sure that every item we try to use actually exists.
The following are examples of items in Rune:
std::result::Result
(a type)std::iter::range
(a function)The first refers to the Result
enum, and the second is the range
function.
They both live within their corresponding std
module. Result
is a bit
special even, since it's part of the prelude, allowing us to use it without
importing it. But what about range
?
If we wanted to use range
we would have to import it first with a use
statement:
use std::iter::range;
pub fn main() {
range(0, 10)
}
$> cargo run --bin rune -- run scripts/book/items_imports/example_import.rn
== Iterator (60µs)
Trying to use an item which doesn't exist results in a compile error:
pub fn main() {
let foo = Foo::new();
}
$> cargo run --bin rune -- run scripts/book/items_imports/missing_item.rn.fail
error: compile error
┌─ scripts/book/items_imports/missing_item.rn.fail:2:15
│
2 │ let foo = Foo::new();
│ ^^^^^^^^ missing item `Foo::new`
Every item used in a Rune program must be known at compile time. This is one of the static guarantees every Rune script are has to fulfill. And is one important point where it differs from Lua or Python.
Rune has support for modules purely defined in Rune itself. This is done using
the mod
keyword. And the module can either be loaded from a different file
matching the name of the module or defined directly inside of the source file.
The following is an example of an inline module:
mod foo {
pub fn get_number() {
1
}
}
mod bar {
pub fn get_number() {
2
}
}
pub fn main() {
foo::get_number() + bar::get_number()
}
$> cargo run --bin rune -- run scripts/book/items_imports/inline_modules.rn
== 3 (33.2µs)
And this is the equivalent modules loaded from the filesystem. These are three separate files:
mod foo;
mod bar;
pub fn main() {
foo::get_number() + bar::get_number()
}
// file: ./foo/mod.rn
pub fn get_number() {
2
}
// file: ./bar.rn
pub fn get_number() {
1
}
$> cargo run --bin rune -- run scripts/book/items_imports/modules.rn
== 3 (37.5µs)
Every item used has to be visible to that item. This is governed by Runes visibility rules, which are the following:
pub
or
pub(crate)
.pub(self)
, making the item
only visible in the module in which they are defined.The available visibility modifiers are:
pub
- the item is visible from anywhere.pub(crate)
- the item is visible in the same crate.pub(super)
- the item is visible in the parent item only.pub(self)
- the item is only visible to other items in the same module.pub(in path)
- the item is only visible in the specified path. This is not
supported yet.Note that Rune doesn't have support for crates yet, meaning
pub(crate)
andpub
are currently effectively equivalent.