Crates and source files
Syntax
Crate :
UTF8BOM?
SHEBANG?
InnerAttribute*
Item*
Lexer
UTF8BOM :\uFEFF
SHEBANG :#!
~[[
\n
] ~\n
*
Note: Although Rust, like any other language, can be implemented by an interpreter as well as a compiler, the only existing implementation is a compiler, and the language has always been designed to be compiled. For these reasons, this section assumes a compiler.
Rust's semantics obey a phase distinction between compile-time and run-time.1 Semantic rules that have a static interpretation govern the success or failure of compilation, while semantic rules that have a dynamic interpretation govern the behavior of the program at run-time.
The compilation model centers on artifacts called crates. Each compilation processes a single crate in source form, and if successful, produces a single crate in binary form: either an executable or some sort of library.2
A crate is a unit of compilation and linking, as well as versioning, distribution and runtime loading. A crate contains a tree of nested module scopes. The top level of this tree is a module that is anonymous (from the point of view of paths within the module) and any item within a crate has a canonical module path denoting its location within the crate's module tree.
The Rust compiler is always invoked with a single source file as input, and
always produces a single output crate. The processing of that source file may
result in other source files being loaded as modules. Source files have the
extension .rs
.
A Rust source file describes a module, the name and location of which — in the module tree of the current crate — are defined from outside the source file: either by an explicit Module item in a referencing source file, or by the name of the crate itself. Every source file is a module, but not every module needs its own source file: module definitions can be nested within one file.
Each source file contains a sequence of zero or more Item definitions, and may optionally begin with any number of attributes that apply to the containing module, most of which influence the behavior of the compiler. The anonymous crate module can have additional attributes that apply to the crate as a whole.
# #![allow(unused_variables)] #fn main() { // Specify the crate name. #![crate_name = "projx"] // Specify the type of output artifact. #![crate_type = "lib"] // Turn on a warning. // This can be done in any module, not just the anonymous crate module. #![warn(non_camel_case_types)] #}
The optional UTF8 byte order mark (UTF8BOM production) indicates that the file is encoded in UTF8. It can only occur at the beginning of the file and is ignored by the compiler.
A source file can have a shebang (SHEBANG production), which indicates to the operating system what program to use to execute this file. It serves essentially to treat the source file as an executable script. The shebang can only occur at the beginning of the file (but after the optional UTF8BOM). It is ignored by the compiler. For example:
#!/usr/bin/env rustx
fn main() {
println!("Hello!");
}
Preludes and no_std
All crates have a prelude that automatically inserts names from a specific
module, the prelude module, into scope of each module and an extern crate
into the crate root module. By default, the standard prelude is used.
The linked crate is std
and the prelude module is std::prelude::v1
.
The prelude can be changed to the core prelude by using the no_std
attribute on the root crate module. The linked crate is core
and the
prelude module is core::prelude::v1
. Using the core prelude over the
standard prelude is useful when either the crate is targeting a platform that
does not support the standard library or is purposefully not using the
capabilities of the standard library. Those capabilities are mainly dynamic
memory allocation (e.g. Box
and Vec
) and file and network capabilities (e.g.
std::fs
and std::io
).
Warning: Using no_std
does not prevent the standard library from being linked
in. It is still valid to put extern crate std;
into the crate and dependencies
can also link it in.
Main Functions
A crate that contains a main
function can be compiled to an executable. If a
main
function is present, it must take no arguments, must not declare any
trait or lifetime bounds, must not have any where clauses, and its return
type must be one of the following:
()
Result<(), E> where E: Error
Note: The implementation of which return types are allowed is determined by the unstable
Termination
trait.
The no_main
attribute
The no_main
attribute may be applied at the crate level to disable
emitting the main
symbol for an executable binary. This is useful when some
other object being linked to defines main
.
The crate_name
attribute
The crate_name
attribute may be applied at the crate level to specify the
name of the crate with the MetaNameValueStr syntax.
#![crate_name = "mycrate"]
The crate name must not be empty, and must only contain Unicode alphanumeric
or -
(U+002D) characters.
This distinction would also exist in an interpreter. Static checks like syntactic analysis, type checking, and lints should happen before the program is executed regardless of when it is executed.
A crate is somewhat analogous to an assembly in the ECMA-335 CLI model, a library in the SML/NJ Compilation Manager, a unit in the Owens and Flatt module system, or a configuration in Mesa.