Съдържание на курса

Урок 0 — Инсталиране на Rust в твоя Linux Mint

От Dorian Chávez · основател на Hábil и архитект на интеграции ·

Време: 90 мин.

Какво изграждаш: твоята среда и първата ти програма с cargo.

Какво научаваш: защо не apt install rustc, rustup, rustc срещу cargo, cargo new/build/run/check, книгата и Rustlings без връзка с интернет, как се чете грешка на компилатора.

След края ще можеш да

  • Инсталираш стабилния Rust с rustup и да обясниш защо не е добре да разчиташ на apt install rustc.
  • Разпознаеш дали терминалът използва инструментите, управлявани от rustup.
  • Разграничиш работата на rustc от работата на cargo и да знаеш кой от двата да използваш във всеки случай.
  • Създадеш проект с cargo new, да го компилираш, да го изпълниш и да го провериш с cargo check.
  • Отвориш The Rust Book без връзка с интернет и да инсталираш Rustlings, за да упражняваш локално.
  • Прочетеш докрай диагностично съобщение на rustc, да откриеш реда, който го причинява, и да изпробваш предложеното поправяне.

Защо, преди как

Този урок не прилича на урок по Rust, защото още не преподава ownership, типове или match. Въпреки това той определя важна част от начина, по който ще учиш езика: от първия ден ще работиш със същата верига от инструменти, със същите конвенции и със същия вид грешки, които използва един истински проект. Да инсталираш нещо, което „горе-долу се компилира“, е достатъчно за изолирано упражнение; да инсталираш правилната среда е необходимо, за да следваш курс, да четеш актуална документация и да построиш revisor без инструментът да се превърне в допълнителен проблем.

Курсът е написан и проверен със стабилния Rust 1.98.1 и издание (edition) 2024. Това е конкретна отправна точка, за да имат програмите, съобщенията и примерите еднакъв смисъл за всички; с по-нова стабилна версия програмите трябва да се държат по същия начин, макар формулировката на някое съобщение на компилатора да може да се промени. Rust публикува нова стабилна версия приблизително на всеки шест седмици. Linux Mint, от своя страна, наследява голяма част от пакетите си от Ubuntu, а LTS дистрибуцията залага на стабилност на системата: замразява основните версии и прилага кръпки за сигурност. Това е разумно решение за системните програми; не е добър начин да следиш отблизо език, чиято екосистема, документация и инструменти се променят често.

Затова apt install rustc изглежда, че работи в началото, а по-късно може да обърка. Той инсталира компилатор на име rustc, но не непременно компилатора, който използват The Rust Book, скорошните примери или проектите, които ще намираш. Проблемът не винаги се проявява като „версията ти е стара“. Понякога се явява като непозната възможност на езика, като издание, което не съществува, като различно предложение на компилатора или като зависимост, която вече не приема тази версия. Това е най-лошият вид повреда при подготовката: проявява се по-късно и прилича на грешка в твоята програма.

Rust решава това с rustup. Той не е просто инсталатор: той е официалният мениджър на toolchain-ове на Rust. Един toolchain (набор от инструменти) обединява версия на rustc, cargo, стандартната библиотека, документацията и свързаните компоненти, които трябва да работят заедно. rustup инсталира стабилния канал и поставя изпълнимите му файлове на предвидимо място в папката на твоя потребител. Когато дойде време за обновяване, сменяш целия този набор с rustup update stable, без да смесваш системни пакети и без да теглиш файлове на ръка.

Сравнението с Go помага да се разбере решението. В Go инсталира официалната дистрибуция, защото и пакетът на дистрибуцията можеше да остане замръзнал; Rust прави този проблем по-видим, защото ритъмът му на публикуване е по-къс и защото cargo обединява компилация, зависимости, тестове, форматиране и статичен анализ. И в двата курса се изгражда един и същ revisor: инструмент, който чете списък със услуги, проверява ги и докладва състоянието им. В Go go събира много задачи. В Rust cargo играе тази роля около rustc. Разликата не променя дисциплината: работи се в рамките на проект, компилира се с повторяем инструмент и се чете диагностиката, преди да се променя кодът наслуки.

Целта не е да запомниш списък от команди. Целта е да изградиш прост мисловен модел. rustc превръща един Rust файл в изпълним код и докладва грешките на езика. cargo разбира цял проект: знае името му, изданието, зависимостите, тестовете, профилите на компилация и структурата на файловете; после извиква rustc с правилните аргументи. В началото ще използваш rustc директно, за да видиш без шум какво прави компилаторът. В ежедневната работа ще използваш cargo, защото една истинска програма рядко се състои от един файл без зависимости.

Другото важно решение в този урок е как да отговаряш на грешка. Rust не се опитва да отгатне какво си искал да кажеш, нито оставя съмнителен код да мине, за да се провали по-късно. Компилаторът спира компилацията, посочва както произхода, така и проблемното използване и в много случаи предлага конкретна промяна. Това не означава, че всички съобщения са лесни от първия ден; означава, че си струва да ги четеш докрай. В Rust компилаторът е част от процеса на учене. Следващите уроци ще те накарат да предизвикваш нарочно грешки със собственост, заемания и типове, защото ще разбереш повече, като диагностицираш истинска повреда, отколкото като заучаваш изолирано правило.

Понятията

rustup инсталира и управлява toolchain-а

Препоръчаната инсталация в Linux Mint е тази, публикувана от самия проект Rust:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Преди да изпълниш команда, която изтегля и изпълнява скрипт, си струва да я разбереш. curl изтегля инсталатора; --proto '=https' ограничава изтеглянето до HTTPS; --tlsv1.2 изисква модерна TLS връзка; -sSf кара командата да се провали, ако сървърът върне грешка; а | sh подава изтегленото съдържание на командния интерпретатор. Това е официалният метод, но фактът, че е официален, не премахва отговорността да проверяваш какво изпълняваш.

Ако предпочиташ първо да го прегледаш, изтегли файла, прочети го и го изпълни едва след като го провериш:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o rustup.sh
less rustup.sh
sh rustup.sh

Инсталаторът предлага инсталация по подразбиране. Избери опцията 1, която инсталира стабилния канал за твоята платформа. След като приключи, отвори нов терминал. Ако искаш да използваш Rust в текущия терминал, без да го затваряш, зареди файла със средата, който инсталаторът е конфигурирал:

source "$HOME/.cargo/env"

Важното място е ~/.cargo/bin. Там rustup поставя програмите, които извикваш: rustup, rustc, cargo, clippy-driver и други. Терминалът намира само команди, които са в променливата му PATH; затова може да съществува правилна инсталация на диска и въпреки това да се появи command not found. Инсталаторът се опитва да обнови началната ти конфигурация, но всеки shell и всеки терминал може да чете различни файлове.

Провери инсталацията с тези команди:

rustup show active-toolchain
rustc --version
cargo --version
type -a rustc
type -a cargo

Първата показва активния toolchain. Следващите две трябва да покажат Rust 1.98.1 или по-нова стабилна версия, ако вече си обновил средата. type -a е особено полезна, ако някога си инсталирал Rust с apt: изброява всички съвпадения, които shell-ът намира, и позволява да откриеш, че изпълняваш стар бинарен файл преди този от ~/.cargo/bin.

Не бъркай обновяването на Linux Mint с обновяването на Rust. За да обновиш стабилния toolchain, използвай:

rustup update stable

Не е нужно да го пускаш преди всяка команда; добре е да го правиш периодично и преди да започнеш сесия след няколко седмици пауза. Ако вече си актуален, rustup ще го съобщи. Целта не е да гониш номера на версии за спорта, а да държиш подравнени компилатора, документацията, примерите и инсталираните компоненти.

В revisor това решение се вижда още от корена. Проектът декларира издание 2024 и Cargo изгражда всичките му модули с активния toolchain. Няма „версия на Rust“, скрита във всеки файл: конфигурацията на пакета фиксира езика, на който говори проектът, а lockfile-ът фиксира конкретните версии на зависимостите му, така че една повторена компилация да разреши същия набор.

PATH и компилаторът, който наистина изпълняваш

Когато напишеш rustc, shell-ът не търси из целия диск. Обхожда папките, изброени в PATH, по ред, и изпълнява първото съвпадение. Това правило обяснява две чести диагностики. Ако в тези папки няма никакъв rustc, bash обикновено показва:

rustc: command not found

Ако има такъв, но идва от по-ранна инсталация с apt, командата може да работи и да покаже неочаквана версия. Този случай е по-подвеждащ: не прилича на проблем с инсталацията, но курсът би се компилирал с инструмент, различен от очаквания.

Първо потвърди кой shell използваш и как е стартиран:

echo "$SHELL"
echo "$0"
printf '%s\n' "$PATH"

При обичайна инсталация с Bash ~/.bashrc се зарежда за интерактивните shell-ове, а ~/.profile — за начална сесия. В Zsh еквивалентният файл за интерактивни сесии обикновено е ~/.zshrc. Файлът, който rustup създава, ~/.cargo/env, добавя ~/.cargo/bin към PATH. Изпълнението на source "$HOME/.cargo/env" в текущия терминал е директна проверка: ако след това rustc --version работи, проблемът е бил в средата на shell-а, а не в компилатора.

Не добавяй дублирани пътища отново и отново, без да провериш какво се е случило. Първо използвай type -a rustc. Ако се появи път от ~/.cargo/bin, rustup е достъпен в PATH. Ако преди него се появи път като /usr/bin/rustc, има системна инсталация, която има приоритет. В този случай първо установи кои пакети са инсталирани и кой бинарен файл използва shell-ът; не се опитвай да го оправяш, като копираш изпълними файлове или променяш символни връзки на ръка.

revisor не зависи от фиксиран път към компилатора. Това е предимство на работата с cargo: инструментът извиква rustc на активния toolchain и запазва резултата от компилациите в target/. Затова един проект на Cargo може да се построи по същия начин на друг компютър с правилна инсталация, без кодът да съдържа лични пътища или команди, специфични за твоята машина.

rustc: компилаторът и първата програма

rustc е компилаторът на Rust. Получава изходен код, проверява дали спазва правилата на езика и, ако всичко е наред, произвежда изпълним файл. За малък файл е полезно да го извикваш директно, защото позволява да се види точната връзка между изходен код, компилация и получена програма. Всяка фигура в този курс се компилира по този начин, за да съответства документираният изход на кода, който четеш.

Фиг. 0.1 | Първата програма.

// fig00_01.rs
fn main() {
    println!("hola, ya tengo Rust");
}
$ rustc --edition 2024 fig00_01.rs && ./fig00_01
hola, ya tengo Rust

fn main() декларира функцията, с която започва една изпълнима програма. Rust търси точно функция на име main, за да започне. Вътре println! отпечатва текст и добавя нов ред. Знакът ! не е украса: println! е макрос. Макросите генерират или трансформират код по време на компилацията; засега е достатъчно да запомниш конвенцията, че имената, които завършват на !, не са обикновени функции. The Rust Book се връща към тази тема в глава 20.

Флагът --edition 2024 избира текущото издание на езика. Изданието не означава, че кодът ти се превръща автоматично на различен език всяка година; то е начин Rust да може да подобрява правила и синтаксис, без тихо да чупи съществуващи проекти. Проектът revisor декларира същото издание в своя манифест. Примерите в курса го посочват изрично, за да не зависи командата на една фигура от изданието по подразбиране на конкретна инсталация.

Тази директна употреба на rustc е нарочно малка. Ако имаше два файла, библиотека, тестове, външни зависимости, опции за оптимизация и различни целеви платформи, да пишеш на ръка правилното извикване на компилатора би станало крехко. Тук влиза cargo. Връзката не е съревнование между две програми: Cargo организира, Rustc компилира. Когато използваш cargo build, Cargo в крайна сметка извиква rustc вместо теб с пътищата, изданието и флаговете, които проектът изисква.

Същото важи и в revisor: бинарният файл има функция main, но не се компилира, като се изолира този файл с rustc src/main.rs. Той импортира модули от локалната библиотека и външни crate-ове; изисква манифеста и структурата, която Cargo познава. Фигурите в този урок учат механизма на компилацията. По-късните уроци прилагат този механизъм към съставна програма.

cargo: проектът преди файла

Създай първия си проект в своя собствена работна папка:

mkdir -p "$HOME/w/curso-rust"
cd "$HOME/w/curso-rust"
cargo new hola
cd hola

cargo new hola създава папка на име hola, манифест Cargo.toml и файла src/main.rs. Ако Git е инсталиран и Cargo може да инициализира хранилище, подготвя също Git и .gitignore; ако Git не е наличен, проектът си остава валиден. Минималният резултат има тази структура:

hola/
├── Cargo.toml
├── .gitignore
└── src/
    └── main.rs

Cargo.toml е манифестът на пакета. Записва идентичността на проекта, неговото издание, зависимостите му и някои решения за построяването. Файлът не е административна подробност: той е това, което позволява на друг човек да изпълни същия cargo build, без да възстановява на ръка списъка с аргументи на компилатора. Когато Cargo разрешава зависимости, създава и Cargo.lock; този файл записва конкретното разрешаване, така че компилациите да са повторяеми.

revisor вече е завършен проект на Cargo. Ето истинския му манифест:

[package]
name = "revisor"
version = "0.1.0"
edition = "2024"
description = "El revisor del curso de Rust: consulta una lista de servicios a la vez y reporta cuáles responden."

[dependencies]
anyhow = "1.0.104"
clap = { version = "4.6.7", features = ["derive"] }
futures = "0.3.34"
reqwest = { version = "0.13.5", features = ["json"] }
serde = { version = "1.0.229", features = ["derive"] }
serde_json = "1.0.151"
yaml_serde = "0.10.7"
tokio = { version = "1.53.1", features = ["full"] }

[profile.release]
strip = true              # quita símbolos
opt-level = "z"           # optimiza para tamaño
lto = true                # optimización entre módulos
codegen-units = 1
panic = "abort"           # sin desenrollado de pila

[dev-dependencies]
serde_json = "1.0.151"

Не е нужно още да разбираш зависимостите, нито профила за освобождаване. Важното е да разпознаеш формата: [package] описва пакета; [dependencies] изброява какво му трябва, за да се компилира; [profile.release] променя начина, по който ще се построи крайният бинарен файл. В урок 4 ще се запознаеш със зависимостите за грешки и сериализация, в 6 — с реда на модулите и тестовете, а в 8 — с профила за освобождаване. Днес е достатъчно да разбереш защо един проект се нуждае от манифест и защо не е добре да заместваш Cargo с дълга ръчна команда на rustc.

Изпълни току-що създадения проект с:

cargo run

Първия път Cargo компилира пакета и после изпълнява бинарния файл. При следващите изпълнения преизползва артефактите, които не са се променили. За разлика от rustc fig00_01.rs, не е нужно да пишеш името на файла, нито името на изпълнимия файл: Cargo познава конвенцията src/main.rs и знае, че пакетът hola произвежда бинарния файл hola.

Тази конвенция намалява повтарящите се решения. Една програма на Rust може да се организира по няколко начина, но Cargo предлага обща структура за честите случаи. Проектът, който създаде днес, съдържа само src/main.rs, бинарния файл. Когато отвориш revisor, ще разпознаеш и src/lib.rs, библиотеката на пакета. Това разделяне не се измисля в урок 6: Cargo го разпознава по конвенция, също както разпознава src/main.rs.

cargo build, run, check и работният цикъл

Командите на Cargo не са синоними. Всяка отговаря на различен въпрос, който си задаваш, докато работиш:

cargo run
cargo build
cargo build --release
cargo check
cargo test
cargo clippy
cargo fmt

cargo run отговаря на „компилира ли се програмата ми и какво прави?“. Първо построява необходимото и после изпълнява бинарния файл. Това е командата, която ще използваш, когато промениш някой изход, изпробваш клон на програмата или искаш да наблюдаваш поведение. За проекта hola трябва да отпечата съобщението, което е в src/main.rs.

cargo build отговаря на „мога ли да произведа бинарния файл?“. Компилира пакета, но не го изпълнява. В режим на разработка оставя артефактите в target/debug/; не е нужно да учиш този път наизуст, но е полезно да знаеш, че Cargo не пълни корена на проекта с изпълними и междинни файлове. Така изходният код и резултатите от компилацията остават разделени.

cargo build --release произвежда профила за освобождаване, обикновено с повече оптимизация и с резултати в target/release/. Разликата има значение, когато предаваш завършения revisor или измерваш производителността му. Не сравнявай времена за изпълнение на бинарен файл за разработка с изводи за производителността на Rust: профилът за разработка дава предимство на бързата компилация и удобното отстраняване на грешки; профилът за освобождаване дава предимство на получената програма. Cargo.toml на revisor показва, че този профил може дори да настройва размера, оптимизацията между модулите и поведението при panic!.

cargo check отговаря на „приема ли компилаторът кода ми?“. Проверява типове, заемания, модули и голяма част от работата по компилацията, но не довършва генерирането на изпълним бинарен файл. В проект, който расте, може да спести време. Използвай я, докато пишеш, особено когато искаш само да знаеш дали една промяна е валидна; използвай cargo run, когато искаш и да изпълниш поведението. Нито една от двете команди не замества другата: едната проверява бързо, а другата проверява и резултата при изпълнение.

cargo test компилира и изпълнява тестове. В този урок още не си писал тестове, но ще започнеш да ги виждаш в урок 6. cargo clippy изпълнява официалния linter и ти посочва шаблони, които се компилират, но обикновено са объркващи, неефективни или неидиоматични. cargo fmt прилага стандартното форматиране на Rust. Това е същата дисциплина като gofmt в Go: не се хаби време в спорове за подравняването на всеки файл, оставя се инструментът да даде еднакъв отговор.

revisor използва точно този цикъл. Преди да публикуваш промяна, е добре да изпълниш от programas/revisor/ тези команди:

cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --check

Първата проверява поведението; втората превръща предупрежденията на Clippy в откази, за да не бъдат пренебрегвани; третата потвърждава, че кодът вече има очакваното форматиране. Не бива още да ги изпълняваш, за да „разбереш“ изхода им. Запази ги като справка за рутината, до която ще стигнеш, докато изграждаш програмата.

Непроменливост по подразбиране и първият разговор с rustc

Rust смята за непроменлива всяка променлива, създадена с let, освен ако не напишеш mut. Това не е пречка, поставена, за да удължи кода. Това е видима декларация за намерение: ако една стойност трябва да се променя, читателят и компилаторът трябва да могат да го видят на мястото, където е дефинирана променливата.

Фиг. 0.2 | Програма, която не се компилира.

// fig00_02.rs
fn main() {
    let x = 5;
    x = 6;
    println!("{x}");
}
$ rustc --edition 2024 fig00_02.rs
error[E0384]: cannot assign twice to immutable variable `x`
 --> fig00_02.rs:4:5
  |
3 |     let x = 5;
  |         - first assignment to `x`
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable
  |
help: consider making this binding mutable
  |
3 |     let mut x = 5;
  |         +++

warning: value assigned to `x` is never read
 --> fig00_02.rs:3:13
  |
3 |     let x = 5;
  |             ^ this value is reassigned later and never used
4 |     x = 6;
  |     ----- `x` is overwritten here before the previous value is read
  |
  = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0384`.

Решението, предложено от компилатора, е правилно, ако наистина искаш да промениш стойността. Думата mut се пише при декларацията, не при последващото присвояване. Така който чете блока, знае от самото начало, че x е част от променливото състояние на тази функция.

Фиг. 0.3 | Същата променлива, вече променлива (mutable).

// fig00_03.rs
fn main() {
    let mut x = 5;      // mut = mutable
    println!("{x}");
    x = 6;              // ahora sí
    println!("{x}");
}
$ rustc --edition 2024 fig00_03.rs && ./fig00_03
5
6

Непроменливостта по подразбиране помага да се намалят случайните промени и подготвя почвата за ownership и заеманията. В други езици е обичайно да се променя една променлива, защото езикът го позволява, и едва после да се питаш кой е зависел от предишната ѝ стойност. Rust изисква да декларираш тази възможност от самото начало. Не премахва всички грешки, но превръща едно неявно допускане в проверимо свойство.

В revisor има променливост само там, където операцията наистина я изисква. Функцията, която подрежда редовете, създава вектор и после го подрежда на място; затова променливата се декларира mut:

fn ordenadas<'a>(servicios: &'a [Servicio], estados: &'a [Estado]) -> Vec<Fila<'a>> {
    let mut filas: Vec<Fila<'a>> = servicios.iter().zip(estados).collect();
    filas.sort_by(|a, b| a.0.nombre.cmp(&b.0.nombre));
    filas
}

mut не се пише по навик. filas.sort_by(...) променя вектора, така че декларацията го съобщава. Напротив, servicios и estados са референции, които тази функция само разглежда; те не се декларират като променливи. Тази разлика, малка в тази функция, става важна, когато няколко части на една програма се опитват да използват едни и същи данни. Урок 2 обяснява правилата, които Rust прилага, за да са тези употреби безопасни.

The Rust Book и Rustlings като локална практика

The Rust Book е официалният текст за справка на курса. rustup инсталира локално копие на документацията, така че можеш да я отвориш без връзка с интернет, след като инсталацията е приключила:

rustup doc --book

Тази команда отваря началната глава в браузъра по подразбиране. Ако нямаш графична среда или предпочиташ да намериш други документи, rustup doc --help показва наличните опции. Локалното копие не замества обновяванията: ако обновиш toolchain-а, локалната документация се обновява заедно с него. Това е още една причина да държиш компилатора и документацията заедно.

Прочети докрай глава 1 на The Rust Book: инсталация, „Hello, world!“ и „Hello, Cargo!“. Не я прескачай, защото вече си създал проект. Това, което направи тук, ти дава контекст, за да я четеш по-бързо; главата подрежда понятията и обяснява конвенциите, които ще се появяват отново през целия курс. Глава 2, която включва играта за налучкване, съответства на урок 1 заедно с основите от глава 3.

Rustlings допълва книгата с малки упражнения, които се решават чрез редактиране на локални файлове. Първоначалната му инсталация изисква достъп до мрежата, за да изтегли Cargo програмата; след това папката с упражненията и техният код живеят на твоя компютър. Инсталирай и инициализирай го така:

cargo install rustlings
rustlings init
cd rustlings
rustlings

Интерактивната команда наблюдава упражненията, показва ти кое се проваля и ги проверява отново, докато запазваш промените. Не използвай Rustlings като колекция от отговори, които трябва да се зачеркнат. Редът в курса е умишлен: първо прочети главата от The Rust Book, после реши свързаните с нея упражнения и после приложи идеята към revisor. На този етап инсталирай Rustlings и се запознай с неговата папка; в урок 1 ще работиш по секциите му variables, functions, if и primitive_types.

Книгата и упражненията изпълняват различни функции. The Rust Book обяснява модела и назовава частите му; Rustlings те принуждава да пипнеш кода и да получиш конкретна грешка. revisor е задачата за интеграция: не е изолирано упражнение, а същата програма, която вече построи в Go, сега с решенията на Rust. Трите източника се подкрепят взаимно. Ако едно обяснение ти изглежда абстрактно, опитай упражнение; ако едно упражнение ти се струва механично, върни се към главата; ако и двете вече са ясни, намери шаблона в истинския проект.

Грешката, която ще видиш

Централната грешка на този урок е E0384, показана цялата на Фиг. 0.2. Не я чети като стена от текст. Чети я по ред. Първият ред назовава кода на диагностиката, E0384, и обобщава проблема: не можеш да присвояваш два пъти на непроменлива променлива. Този код служи, за да поискаш от компилатора по-подробно обяснение:

rustc --explain E0384

Редът, който започва с --> fig00_02.rs:4:5, локализира опита за присвояване: файл, ред и колона. Редовете с номера показват достатъчно контекст, за да не се налага да търсиш на сляпо. Маркировката ^^^^^ посочва точната част, която причинява грешката. Преди нея се появява първото присвояване, на ред 3, защото Rust не само съобщава къде е открил проблема: показва и произхода на условието, което го прави невалиден.

Секцията help: заслужава особено внимание. В този случай предлага да се промени let x = 5; на let mut x = 5;, а маркировките +++ показват какъв текст да се добави. Не прилагай механично всички предложения. Първо провери намерението: ако x не би трябвало да се променя, правилното решение не е да добавиш mut, а да премахнеш или преосмислиш последващото присвояване. Компилаторът може да предложи локално поправяне; ти решаваш дали то представлява правилния дизайн.

Същата диагностика включва и предупреждение: първата стойност, 5, никога не се чете, защото веднага се презаписва. Предупреждението само по себе си не пречи на компилирането, но дава полезна информация. Ако направиш x променлива, без да погледнеш предупреждението, програмата ще продължи да има излишно присвояване. Версията от Фиг. 0.3 отпечатва 5, преди да го промени, така че и двете стойности имат смисъл и програмата не генерира предупреждения.

Когато изпълниш същата грешка в проект с cargo run или cargo check, Cargo ще покаже диагностиката на rustc заедно с контекст на пакета и пътя src/main.rs. Правилото не се променя: започни от първата грешка, прочети нейните бележки и помощ, поправяй по една причина и компилирай отново. Една начална грешка може да предизвика няколко последващи; опитът да се поправят всички наведнъж обикновено скрива истинската причина.

Има и други грешки при подготовката, които не са кодове на Rust, защото се случват, преди компилаторът да успее да анализира програмата ти. Ако cargo или rustc не съществуват за терминала, проблемът е PATH; зареди отново ~/.cargo/env и провери type -a cargo. Ако компилацията стигне до свързване (linking) и се появи съобщение, подобно на error: linker 'cc' not found, липсва компилаторът за C, който Rust използва за свързване в Linux Mint. Инсталирай пакета с инструменти за построяване на дистрибуцията и изпълни командата отново:

sudo apt install build-essential

Не бъркай този случай с „Rust не се е инсталирал“. rustc --version може да работи съвършено; повредата се появява по-късно, когато компилаторът трябва да превърне компилираните обекти в изпълним файл на системата. Разделянето на етапа, който се проваля, предотвратява произволните поправки.

Какво се прави погрешно

  • Инсталиране на Rust с apt install rustc и приемане за даденост, че името на пакета гарантира актуален toolchain. Проблемът не е, че пакетът е безполезен; а че следва календара на дистрибуцията, не този на Rust. За този курс използвай rustup, проверявай rustc --version и обновявай периодично стабилния канал.

  • Смесване на инсталация от apt с друга от rustup, без да провериш коя печели в PATH. Наличието на два изпълними файла на име rustc не води непременно до незабавна грешка. Може да компилираш с неправилната версия с дни. Използвай type -a rustc и type -a cargo, преди да променяш началните файлове или да премахваш пакети.

  • Използване на rustc за цял проект по навик. За фигура от един файл той е отличен учебен инструмент. За revisor би означавало да възстановяваш на ръка зависимости, пътища, издание, модули и профили. Използвай cargo от корена на проекта; остави него да изгради извикването на rustc.

  • Използване на cargo run всеки път, когато искаш да знаеш дали кодът се компилира. Работи, но построява и изпълнява, дори когато само поправяш типове или заемания. По време на бързо редактиране cargo check дава по-пряка обратна връзка. Когато трябва да наблюдаваш поведението, използвай cargo run.

  • Измерване на производителност с бинарен файл за разработка. cargo build и cargo run използват по подразбиране профила за разработка. Когато курсът стигне до сравняване на размер, скорост или предаване на бинарния файл, използвай cargo build --release. Без това разграничаване едно измерване отговаря повече за избрания профил, отколкото за програмата.

  • Пренебрегване на предупреждение, защото „не пречи да се компилира“. Предупрежденията обикновено сочат неизползвани стойности, мъртъв код или объркващи конструкции. Този курс компилира правилните фигури с предупреждения, третирани като грешки, за да не крие показаният изход проблеми. Прави същото в рутината си: разбери предупреждението или премахни причината му.

  • Четене само на първия ред на една грешка. Първият ред назовава категорията; следващите редове казват къде е станало, коя предишна стойност го обяснява, какви бележки се прилагат и каква алтернатива разглежда компилаторът. Да копираш само „error E0384“, за да го търсиш, губи голяма част от отговора, който вече е пред теб.

  • Инсталиране на Rustlings и решаване на упражненията с копирани отговори. Завършено упражнение без разбиране на диагностиката не изгражда мисловния модел, от който ще се нуждаеш за ownership. Прави малки промени, изпълнявай проверката, чети грешката и обяснявай със свои думи защо решението се компилира.

Упражнения

Упражнение 1 — Провери своя toolchain

Инсталирай Rust с rustup, ако още нямаш. Изпълни rustup show active-toolchain, rustc --version, cargo --version и type -a rustc. Запиши кой път използва терминалът за rustc и потвърди, че съответства на ~/.cargo/bin, когато използваш инсталацията, управлявана от rustup.

Упражнение 2 — Създай и обходи проект на Cargo

В работна папка изпълни cargo new saludo-rust и влез в създадената директория. Прочети Cargo.toml и src/main.rs, преди да ги променяш. Смени съобщението с твое и изпълни по ред cargo check, cargo build и cargo run. Обясни на кой въпрос е отговорила всяка команда и какъв файл или резултат си очаквал от всяка.

Упражнение 3 — Предизвикай и обясни E0384

Замени временно съдържанието на src/main.rs с програмата от Фиг. 0.2 и изпълни cargo check. Не поправяй нищо, докато не си установил файла, реда, първото присвояване и предложението, маркирано с help:. После промени декларацията на let mut x = 5;, наблюдавай оставащото предупреждение и промени програмата така, че двете стойности да бъдат прочетени, както във Фиг. 0.3.

Упражнение 4 — Подготви четенето и локалната практика

Отвори The Rust Book с rustup doc --book и прочети изцяло глава 1. Инсталирай Rustlings с cargo install rustlings, изпълни го в локалната му директория и намери как да отвориш отново упражненията, без да зависиш от уеб страница. Напиши кратка бележка, която различава какво получаваш от книгата, какво получаваш от Rustlings и какво ще построиш после в revisor.

Решения

Решение 1

Правилната инсталация показва активен стабилен toolchain и позволява да се изпълнят както rustc --version, така и cargo --version. Точният изход може да се промени при обновяване на Rust, но двата инструмента трябва да принадлежат на една и съща стабилна инсталация. type -a rustc трябва да изброява ~/.cargo/bin/rustc като избрания път или поне да ти позволява да обясниш защо друг път има приоритет. Ако не се появи, изпълни source "$HOME/.cargo/env" и провери отново.

Решение 2

cargo check проверява проекта, без да довършва произвеждането на изпълним файл; cargo build компилира пакета и оставя артефакти за разработка в target/debug/; cargo run компилира необходимото и изпълнява бинарния файл. И трите команди трябва да приемат проекта saludo-rust. Изходът на cargo run трябва да е точно съобщението, което си оставил в src/main.rs.

Решение 3

cargo check показва E0384, защото let x = 5; създава непроменлива връзка, а следващият ред се опитва да я присвои отново. Промяната на let mut x = 5; позволява ново присвояване, но първоначално оставя предупреждение, защото 5 се презаписва, без да е използвано. Отпечатването на x преди и след присвояването премахва предупреждението и произвежда двата реда от Фиг. 0.3. Поуката не е „винаги добавяй mut“; тя е да декларираш променливост само когато промяната е част от дизайна.

Решение 4

The Rust Book представя подредено обяснение на инсталацията, началната програма и Cargo; глава 1 е достъпна локално с rustup doc --book. Rustlings предлага редактируеми упражнения и обратна връзка върху локален код, след като го инсталираш и инициализираш неговата директория. revisor е мястото, където тези части се обединяват в приложение: той не замества нито книгата, нито упражненията, а дава непрекъсната задача, върху която да прилагаш понятията от следващите уроци.

Как да разбера, че съм успял

  • rustc --version и cargo --version работят и показват съвместим стабилен toolchain.
  • type -a rustc ми позволява да установя кой компилатор изпълнява моят терминал.
  • rustup update stable приключва без грешки и мога да обясня какво обновява.
  • cargo new saludo-rust създаде проект с Cargo.toml и src/main.rs.
  • cargo check, cargo build и cargo run работят в този проект и знам какво прави всяка.
  • Програмата ми отпечатва съобщението, което съм написал, когато изпълня cargo run.
  • Мога да предизвикам E0384, да посоча реда на произхода му, да прочета помощта му и да поправя програмата, без да оставя предупреждения.
  • rustup doc --book отваря локалния The Rust Book и Rustlings е инициализиран в локална папка.

За по-нататъшно четене

  • The Rust Programming Language, глава 1 — инсталация, първа програма и Cargo. Консултирано на 2 октомври 2026 г.

  • Rust: Install — официална инсталация с rustup, обновяване на toolchain-ове и бележки за PATH. Консултирано на 2 октомври 2026 г.

  • The Cargo Book: Why Cargo Exists — защо Cargo управлява пакети, зависимости и извикванията на rustc. Консултирано на 2 октомври 2026 г.

  • Rustlings — инсталация, инициализация и употреба на локални упражнения паралелно с The Rust Book. Консултирано на 2 октомври 2026 г.

Да обсъдим вашия проект

Предпочитате имейл? Пишете ни на hola@habil.mx