Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Крейты и исходные файлы

Syntax
Crate
    InnerAttribute*
    Item*

Note

Хотя Rust, как и любой другой язык, может быть реализован как интерпретатором, так и компилятором, единственная существующая реализация — это компилятор, и язык всегда проектировался для компиляции. По этим причинам данный раздел предполагает использование компилятора.

Семантика Rust подчиняется фазовому разграничению между временем компиляции и временем выполнения.1 Семантические правила, имеющие статическую интерпретацию, определяют успех или неудачу компиляции, в то время как семантические правила, имеющие динамическую интерпретацию, определяют поведение программы во время выполнения.

Модель компиляции сосредоточена вокруг артефактов, называемых крейтами. Каждый процесс компиляции обрабатывает один крейт в исходной форме и, в случае успеха, производит один крейт в бинарной форме: либо исполняемый файл, либо библиотеку того или иного вида.2

Крейт — это единица компиляции и линковки, а также версионирования, распространения и загрузки во время выполнения. Крейт содержит дерево вложенных областей видимости модулей. Верхний уровень этого дерева — это модуль, который является анонимным (с точки зрения путей внутри модуля), и любой элемент в пределах крейта имеет канонический путь модуля, обозначающий его расположение в пределах дерева модулей крейта.

Компилятор Rust всегда вызывается с одним исходным файлом в качестве входных данных и всегда производит один выходной крейт. Обработка этого исходного файла может привести к загрузке других исходных файлов в качестве модулей. Исходные файлы имеют расширение .rs.

Исходный файл Rust описывает модуль, имя и расположение которого — в дереве модулей текущего крейта — определяются извне исходного файла: либо явным объявлением модуля в ссылающемся исходном файле, либо именем самого крейта.

Каждый исходный файл является модулем, но не каждому модулю нужен свой собственный исходный файл: определения модулей могут быть вложены в один файл.

Каждый исходный файл содержит последовательность из нуля или более определений Элементов и может опционально начинаться с любого количества атрибутов, которые применяются к содержащему модулю, большинство из которых влияют на поведение компилятора.

Анонимный модуль крейта может иметь дополнительные атрибуты, которые применяются к крейту в целом.

Note

Содержимое файла может предваряться шебангом.

#![allow(unused)]
fn main() {
// Указание имени крейта.
#![crate_name = "projx"]

// Указание типа выходного артефакта.
#![crate_type = "lib"]

// Включение предупреждения.
// Это можно сделать в любом модуле, а не только в анонимном модуле крейта.
#![warn(non_camel_case_types)]
}

Функция main

Крейт, содержащий функцию main, может быть скомпилирован в исполняемый файл.

Если функция main присутствует, она не должна принимать аргументов, не должна объявлять ограничений типов (трейтов) или времен жизни, не должна иметь where-предложений, и её возвращаемый тип должен реализовывать типаж Termination.

fn main() {}
fn main() -> ! {
    std::process::exit(0);
}
fn main() -> impl std::process::Termination {
    std::process::ExitCode::SUCCESS
}

Функция main может быть импортирована, например, из внешнего крейта или из текущего.

#![allow(unused)]
fn main() {
mod foo {
    pub fn bar() {
        println!("Hello, world!");
    }
}
use foo::bar as main;
}

Note

Типы из стандартной библиотеки, реализующие Termination:

Неперехваченное внешнее раскручивание стека (unwinding)

Когда “внешнее” раскручивание стека (например, исключение, вставленное из кода C++, или panic! в коде Rust, использующем другой обработчик паники) распространяется за пределы функции main, процесс будет безопасно завершён. Это может принять форму аварийного завершения (abort), и в этом случае не гарантируется, что какие-либо вызовы Drop будут выполнены, а вывод ошибки может быть менее информативным, чем если бы среда выполнения была завершена “нативной” Rust-паникой.

Для получения дополнительной информации см. документацию по панике.

Атрибут no_main

Атрибут no_main может быть применён на уровне крейта, чтобы отключить генерацию символа main для исполняемого бинарного файла. Это полезно, когда какой-либо другой связываемый объект определяет main.

Атрибут crate_name

Атрибут crate_name может быть применён на уровне крейта, чтобы указать имя крейта с помощью синтаксиса MetaNameValueStr.

#![allow(unused)]
#![crate_name = "mycrate"]
fn main() {
}

Имя крейта не должно быть пустым и должно содержать только Юникодные алфавитно-цифровые символы или символы _ (U+005F).


  1. Это разграничение также существовало бы и в интерпретаторе. Статические проверки, такие как синтаксический анализ, проверка типов и линтеры, должны происходить до выполнения программы независимо от того, когда она выполняется.

  2. Крейт в некоторой степени аналогичен сборке (assembly) в модели ECMA-335 CLI, библиотеке в SML/NJ Compilation Manager, юниту (unit) в модульной системе Овенса и Флатта или конфигурации в Mesa.