Rust
Rust — компільована системна мова, що звільняє пам’ять без збирача сміття: ще під час компіляції вона перевіряє, хто володіє значенням і хто його позичає. Саме через цю перевірку в безпечному Rust немає використання звільненої пам’яті й гонок даних — і саме через неї новачки перші тижні сперечаються з компілятором. Сторінка починається з дванадцяти помилок компілятора, які зустрічає кожен, і правила за кожною; далі — володіння й позичання, чого компілятор перевірити не може, потоки й async, помилки й паніки, релізи й редакції до Rust 1.99, п’ять задокументованих кейсів і те, де Rust — не той інструмент.
- Поточна версія
- Rust 1.99 · 1 жовт. 2026
- Пам’ять
- Володіння, перевірене компілятором
- Релізи
- Кожні шість тижнів; редакція — раз на три роки
Дванадцять помилок компілятора, які зустрічає кожен, і правило за кожною
Більшість мов дозволяє написати програму, а помилки пам’яті знайти потім — у продакшені чи під відлагоджувачем. Rust переносить цю мить на час компіляції. Borrow checker — частина компілятора, що стежить, хто володіє кожним значенням і хто його позичає, — відмовляється збирати код, який міг би звернутися до звільненої пам’яті чи влаштувати гонку за спільні дані. Тож перші тижні новачка — це низка повідомлень про помилки, і кожне з них називає правило, а не баг. Ось дванадцять, які зустрічає майже кожен, — з кодом, правилом, яке вона захищає, і звичним виправленням. Для кожного коду є повне пояснення: rustc --explain E0382 і так далі. Наступні розділи посилаються на рядки за номерами.
| # | Помилка | Правило, яке вона захищає | Звичне виправлення |
|---|---|---|---|
| 1 | E0382 · використання переміщеного значення | Присвоєння String, Vec чи Box переміщує значення; старе ім’я мертве | Позичте через &, зробіть .clone() або перебудуйте код, щоб вистачало одного власника |
| 2 | E0384 · не можна вдруге присвоїти незмінній змінній | Змінні незмінні, якщо не оголошені як mut | let mut або затінення новим let |
| 3 | E0596 · не можна позичити як змінюване | Змінювати значення через посилання можна лише з mut-прив’язкою і &mut | Оголосіть mut; приймайте &mut self у методі |
| 4 | E0499 · не можна позичити як змінюване більше ніж раз | Не більше одного &mut на значення одночасно | Закінчіть з одним, перш ніж брати наступний; позичайте окремі поля структури |
| 5 | E0502 · не можна позичити як змінюване, бо вже позичено як незмінне | Читачі або один записувач — ніколи разом | Скопіюйте прочитане, потім пишіть; або дайте читальному позиченню закінчитися |
| 6 | E0505 · не можна перемістити, бо значення позичене | Значення не може піти, поки хтось тримає посилання на нього | Дайте позиченню закінчитися або зробіть клон |
| 7 | E0507 · не можна перемістити значення з-під посилання | Позичальник може дивитися, але не забирати | .clone(), std::mem::take або Option::take() |
| 8 | E0515 · не можна повернути посилання на локальну змінну | Посилання не може пережити те, на що вказує | Поверніть значення у власність — String, а не &str |
| 9 | E0597 · позичене значення живе недостатньо довго | Значення знищується, поки посилання на нього ще використовують | Перенесіть значення в зовнішню область або візьміть у власність |
| 10 | E0106 · бракує специфікатора часу життя | Повернене посилання має сказати, у якого входу воно позичене | Назвіть час життя — fn f<'a>(x: &'a str) -> &'a str — або поверніть значення у власність |
| 11 | E0373 · замикання може пережити поточну функцію | Потік може жити довше за функцію, що його запустила | move — перенесіть дані в замикання; std::thread::scope для позичених даних |
| 12 | E0277 · Rc<…> не можна безпечно передати між потоками | В інший потік можна перемістити лише тип Send, а спільно використовувати — лише Sync; Rc не є жодним | Arc для спільного володіння; Mutex чи атомарні типи для спільних змін |
Володіння: один власник, позичені посилання і жодного збирача
Кожна мова мусить відповісти на одне питання про пам’ять: коли значення безпечно звільнити? Збирач сміття — у Java, Go, Python — відповідає під час виконання, шукаючи значення, на які вже ніщо не вказує, і платить процесором і паузами. C та C++ лишають відповідь програмістові й платять помилками використання звільненої пам’яті та подвійного звільнення. Rust відповідає під час компіляції трьома правилами. Кожне значення має рівно одного власника — змінну, поле, колекцію. Власник один у кожну мить; присвоєння чи передача значення переміщує володіння. А коли власник виходить з області видимості, значення знищується: пам’ять звільняється, файл закривається, блокування знімається — у місці, яке видно в коді.
Переміщення дешевше, ніж звучить. String — це три слова на стеку: вказівник на його байти в купі, довжина й місткість. let b = a; копіює ці три слова й позначає a непридатним; байти в купі ніхто не чіпає. Саме тому існує рядок 1: якби a лишався придатним, два власники звільнили б ті самі байти. Дрібні значення, що не володіють пам’яттю в купі, — цілі числа, bool, char — реалізують Copy і копіюються, а не переміщуються, тож правило їх не зачіпає. .clone() робить справжню глибоку копію; це чесне виправлення рядка 1, коли вам справді потрібні два незалежні значення, і дорога звичка, коли воно лише змушує компілятор замовкнути.
Позичання — спосіб користуватися значенням, не переміщуючи його. &a — спільне посилання: таких може бути скільки завгодно, і жодне не може змінювати значення. &mut a — змінюване посилання: воно може бути лише одне, і поки воно існує, ніхто інший не може навіть читати значення. Це єдине правило — багато читачів або один записувач — і захищають рядки 2–5, і це те саме правило, яке під час виконання забезпечує блокування читачів-записувачів. Rust перевіряє його під час компіляції — для кожного посилання й усюди. Через нього ж ітератор у Rust не можна зробити недійсним: цикл тримає спільне позичання вектора, тож push, що міг би перевиділити вектор під циклом, не компілюється.
Позичання триває від місця, де його створено, до останнього використання, а не до кінця блоку. З редакції 2018 компілятор визначає це за реальним потоком коду — ця зміна звалася non-lexical lifetimes, — і тому код, що на вигляд тримає два позичання, часто компілюється: перше вже закінчилося. Часи життя, анотації 'a з рядка 10, — не спосіб подовжити життя значення. Це мітки, що кажуть компілятору, з якого входу взято повернене посилання, щоб він міг перевірити, що викликач його не переживе. Більшості функцій вони ніколи не потрібні: три правила пропуску дають компілятору вивести їх самому, і він питає лише тоді, коли, скажімо, функція приймає два посилання й повертає одне.
Чого компілятор перевірити не може
Borrow checker доводить вузьке й цінне твердження: у безпечному Rust жодне посилання не вказує на звільнену пам’ять і жодні два потоки не пишуть у ту саму пам’ять без синхронізації. Він не доводить, що програма правильна, і не доводить усього, що звучить як безпека пам’яті. Читати гарантію ширше, ніж вона є, — найдорожче непорозуміння щодо Rust, тож ось межа, проведена точно.
| Помилка | У безпечному Rust | Чому |
|---|---|---|
| Використання після звільнення, подвійне звільнення, завислий вказівник | Неможливі | Володіння й позичання (рядки 1–10) |
| Гонка даних — два потоки пишуть в одну змінну | Неможлива | Send і Sync (рядки 11–12) |
| Читання за межами масиву | Зупиняється під час виконання панікою | Кожен індекс перевіряється на межі |
| Переповнення цілого числа | Паніка в налагоджувальних збірках; тихе загортання в релізних | У релізі перевірки вимкнені, якщо не задати overflow-checks = true |
| Витік пам’яті | Можливий і вважається безпечним | Цикл Rc, mem::forget, Box::leak |
| Взаємне блокування | Можливе | Два потоки беруть два Mutex у протилежному порядку |
| Стан гонки в логіці — перевірив, потім діє | Можливий | Кожен крок синхронізовано, а пару — ні |
Паніка — unwrap(), expect(), індекс | Можлива; зупиняє потік | Паніка безпечна, але це не обробка помилки |
| Логічні помилки | Можливі | Система типів перевіряє пам’ять, а не намір |
unsafe — це межа. Усередині блоку unsafe можна робити п’ять речей, які безпечний Rust забороняє: розіменовувати сирий вказівник; викликати unsafe-функцію, а такою є кожна функція C, досяжна через FFI; читати чи писати змінювану статичну змінну; реалізовувати unsafe-трейт на кшталт Send; читати поля об’єднання (union). Усе інше й далі перевіряється — borrow checker працює і всередині unsafe. Блок — це обіцянка, написана людиною, що інваріанти, яких компілятор не бачить, справді виконуються. Стандартна бібліотека збудована на таких обіцянках — Vec, Mutex і Arc містять unsafe — і загортає їх у безпечні APIApplication Programming Interface — контракт між програмамиПравила, за якими одна програма звертається до іншої: які запити можна надіслати, у якому вигляді й що прийде у відповідь. Для того, хто звертається, це контракт — усе, що за ним, лишається чорною скринькою, і саме тому другий бік можна переписати, не зламавши вас.Докладніше в статті →Усі терміни, тож кожну обіцянку перевіряють один раз ті, хто її написав, а не на кожному виклику.
Ось чому одна помилка в блоці unsafe може вилізти будь-де: безпечна функція, що йому довіряє, може видати зависле посилання, і падіння з’явиться далеко від причини. Межу тримають чесною дві практики. Тримайте unsafe малим і всередині модуля з безпечним публічним API, а над кожним блоком пишіть інваріант у коментарі // SAFETY: — Clippy може цього вимагати. І запускайте тести під Miri — cargo +nightly miri test — інтерпретатором, що виявляє невизначену поведінку (undefined behaviourте, що специфікація лишає відкритимПоведінка, яку мова чи специфікація свідомо лишає невизначеною: програма може впасти, удавати, що працює, або зробити щось зовсім інше, і результат може змінитися з версією компілятора чи платформою. У C, C++ і unsafe Rust саме на це перетворюється помилка памʼяті, бо компілятор має право вважати, що такого не буває.Усі терміни) в unsafe-коді, повз яку проходить звичайний запуск. Дані Android — корисне калібрування: близько 4% їхнього Rust-коду лежить у блоках unsafe, і цей код не виявився схильнішим до помилок, ніж C, — схоже, пильна увага, яку привертає це слово, окупається.
Потоки і async: Send, Sync і середовище, якого Rust не постачає
Рядки 11 і 12 поширюють ті самі правила на потоки. Потік може пережити функцію, що його запустила, тож замикання, передане в thread::spawn, мусить володіти своїми даними — move — або позичати їх усередині std::thread::scope, що гарантує завершення кожного потоку раніше, ніж закінчаться позичені дані. А два трейти-маркери вирішують, що взагалі може перетнути межу потоку. Тип є Send, якщо його можна перемістити в інший потік, і Sync, якщо туди можна передати спільне посилання на нього. Компілятор виводить обидва автоматично з полів типу, тож структура з Rc не є ні тим, ні іншим, і помилка з’являється на spawn, а не в продакшені. Для узагальненого контейнера відповідь залежить від вмісту; таблиця припускає прості, потокобезпечні дані.
| Тип | Send | Sync | Для чого |
|---|---|---|---|
i32, String, Vec<T> | Так | Так | Прості дані |
Rc<T> | Ні | Ні | Спільне володіння в одному потоці — його лічильник не атомарний |
Arc<T> | Так | Так | Спільне володіння між потоками; лічильник атомарний |
RefCell<T> | Так | Ні | Зміна через & в одному потоці з перевіркою під час виконання |
Mutex<T> | Так | Так | Зміна через & між потоками, по одному за раз |
std::sync::MutexGuard | Ні | Так | Утримання блокування — його треба зняти в тому потоці, що його взяв |
Результат — властивість, яку спільнота Rust називає безстрашною паралельністю: гонка даних (data raceдва потоки, одна змінна, без блокуванняДва потоки чи горутини одночасно звертаються до тієї самої памʼяті, принаймні один із них пише, і впорядкувати ці звернення нічим. Результат невизначений — хибне значення, «розірване» читання чи падіння набагато пізніше, — і, на відміну від стану гонки в логіці, його можна виключити механічно: детектором гонок або, у Rust, компілятором.Докладніше в статті →Усі терміни) — це помилка компіляції. Вона не робить паралельні програми правильними — взаємні блокування й гонки «перевірив, потім дій» з таблиці вище лишаються на вас, — але прибирає той клас помилок, на підрахунок якого в Go-коді Uber знадобилося пів року й детектор гонок.
Async у Rust: футури, Tokio і скасування
async fn у Rust, коли її викликають, нічого не робить. Вона повертає футуру — значення, що описує роботу, — і робота виконується лише тоді, коли щось цю футуру опитує. Мова постачає синтаксис і трейт Future, але жодного середовища, яке б опитувало; його обираєте ви, і для серверів на практиці це Tokio — багатопотоковий планувальник, що краде роботу між потоками, плюс таймери й неблокуючий мережевий ввід-вивід. На ньому збудовано Axum, Hyper, Tonic і більшість серверної екосистеми. І проксі Cloudflare Pingora теж — Cloudflare писала, що обрала його, бо крадіжка роботи прибирає проблеми запиту, прив’язаного до одного процесу.
З цього задуму випливають дві пастки. Блокуючий виклик усередині async-задачі — читання файлу через std::fs, важкий для CPUCentral Processing Unit — процесорПроцесор, що виконує інструкції програми. Коли кажуть, що завдання «впирається в CPU», мають на увазі, що воно обмежене обчисленнями, а не очікуванням диска чи мережі, — і лікуються ці два випадки протилежно, тому розрізняти їх варто одразу.Усі терміни цикл, синхронний драйвер бази даних — тримає потік середовища, і кожна інша задача, запланована на ньому, чекає: той самий збій, що й requests.get усередині asyncio в Python. Виносьте таку роботу в tokio::task::spawn_blocking. А задача в багатопотоковому середовищі може переїхати в інший потік на кожному .await, тож усе, що вона тримає через .await, має бути Send. Утримання std::sync::MutexGuard через нього дає «future cannot be sent between threads safely» — рядок 12 в async-формі. Знімайте блокування до очікування або беріть tokio::sync::Mutex, коли блокування справді треба тримати через .await.
Помилки й паніки: Result, оператор ? і unwrap
У Rust немає ні винятків, ні null. Функція, що може зазнати невдачі, повертає Result<T, E> — або Ok(value), або Err(error), — а значення, якого може не бути, — це Option<T>: Some(value) або None. Компілятор не дасть скористатися значенням, не вирішивши, що буде в іншому випадку, а match має покрити кожен випадок, який має тип. Оператор ? робить це дешевим у написанні: let user = load(id)?; повертає помилку викликачеві, якщо вона є, іде далі зі значенням, якщо ні, і дорогою перетворює тип помилки.
Бібліотеки зазвичай визначають власний enum помилок і доручають шаблонний код thiserror; застосунки зазвичай збирають помилки в anyhow::Error і додають контекст на кожному шарі — .context("loading the feature file")? — та сама ідея, що й обгортання через %w у Go. Чого ? не вміє — вирішувати. Десь біля краю програми match або залогована помилка перетворює збій на код статусу, повтор чи запасний варіант, і таке місце мусить існувати.
Паніка — інший шлях. unwrap() і expect() перетворюють Err чи None на паніку; так само діють вихід індексу за межі, RefCell, позичений двічі, і переповнення цілого в налагоджувальній збірці. Паніка розкручує потік — знищуючи все, чим він володів, тож пам’ять не тече й жодне блокування не лишається взятим, — а на сервері зазвичай завершує воркер чи запит. Вона безпечна для пам’яті. Але це не обробка помилки. unwrap() — це записане в код твердження, що збою бути не може, і той, хто його рев’юїть, має спитати, що буде, коли твердження виявиться хибним.
Релізи, редакції, Cargo і який Rust перед вами
Rust 1.0 вийшов 15 травня 2015 року з обіцянкою, що стабільний код і далі компілюватиметься. Нова стабільна версія виходить кожні шість тижнів — Rust 1.99.0 вийшов 1 жовтня 2026 року, — і збирається з нічного каналу через шеститижневу бету. Несумісні зміни в мові приходять лише через редакції, які кожен крейт обирає в Cargo.toml, а крейти різних редакцій вільно лінкуються разом. Редакція може змінити значення коду — ключові слова, типові значення, лінти, — але той самий компілятор підтримує кожну редакцію безстроково.
| Редакція | Компілятор | Що змінилося з того, що ви зустрінете |
|---|---|---|
| 2015 | 1.0, трав. 2015 | Початкова мова |
| 2018 | 1.31, груд. 2018 | async і dyn стають ключовими словами; простіша система модулів; non-lexical lifetimes |
| 2021 | 1.56, жовт. 2021 | Замикання захоплюють окремі поля; TryFrom і TryInto у прелюдії; масиви ітеруються за значенням |
| 2024 | 1.85, лют. 2025 | Блоки unsafe extern; gen зарезервовано; тимчасові значення в if let знищуються раніше; посилання на static mut заборонено |
Cargo — це інструмент збірки, менеджер пакетів і запускач тестів в одному: cargo build, cargo test, cargo doc, плюс rustfmt для форматування й Clippy з кількома сотнями лінтів. Пакети, що звуться крейтами, беруться з crates.io, а Cargo.lock фіксує точні версії, з якими постачається застосунок. Дві звички окупаються. cargo audit чи cargo deny перевіряє lockfileточні версії кожної залежностіФайл, який менеджер пакетів пише поряд зі списком залежностей і в якому записано точну версію кожного встановленого пакета — зокрема тих, що підтягнули ваші залежності. Закомічений у репозиторій, він робить кожне встановлення однаковим; без нього дві збірки того самого коміту можуть виконувати різний код.Усі терміни за базою бюлетенів RustSec у CI/CDContinuous Integration / Continuous Delivery — автоматична збірка й доставкаКожен коміт автоматично складається і проганяється через тести (CI), а придатна збірка так само автоматично їде на сервери (CD). Сенс не в автоматизації як такій, а в тому, що поломку видно за хвилини, а не в день релізу.Докладніше в статті →Усі терміни. А поле rust-version у Cargo.toml вказує найстаріший компілятор, який підтримує крейт, — його MSRV, — і резолвер залежностей редакції 2024 враховує його, коли обирає версії.
П’ять кейсів і що показує кожен
Кожен кейс задокументували ті, з ким він стався: інженерні блоги, власний бюлетень безпеки проєкту, опубліковані дані платформи. Два показують, що Rust дає, два — чого він не дає, а один — звідки насправді береться виграш.
| Кейс | Що сталося | Що це показує |
|---|---|---|
| Discord, лют. 2020 | Read States переїхав з Go на Rust; сплески GC кожні дві хвилини зникли | Пам’ять звільняється у відому мить — немає збирача, що зупиняв би |
| Cloudflare Pingora, вер. 2022 | Заміна Nginx на Rust: приблизно на 70% менше CPU і на 67% менше пам’яті | Виграш дала архітектура не менше, ніж мова |
| CVE-2024-24576, квіт. 2024 | Стандартна бібліотека неправильно екранувала аргументи для пакетних файлів Windows | Безпечний Rust не запобігає логічним помилкам — навіть у std |
| Android, 2019–2025 | Частка помилок безпеки пам’яті впала з 76% вразливостей до менш як 20%, коли новий код перейшов на Rust | Новий код важить більше, ніж переписування старого |
| Cloudflare, 18 лист. 2025 | unwrap() на завеликому файлі конфігурації поклав панікою весь парк проксі | Паніка безпечна, але не оброблена |
Перший кейс — історія Discord зі сторінки про Go, побачена з іншого боку. Без збирача сміття Rust-версія Read States звільняла кожен витіснений запис кешу саме в мить витіснення, тож не було ні періодичного обходу десятків мільйонів живих записів, ні сплеску кожні дві хвилини. Discord повідомив, що латентність, CPU й пам’ять стали кращими, а середній час відповіді «тепер вимірюється в мікросекундах». Дві деталі тримають кейс чесним. Go-сервіс працював на Go 1.9, а пізніші релізи Go помітно покращили збирач; і Discord тоді мусив брати нічний Rust заради async, про що сам і написав. Урок вузький і справжній: для величезної довгоживучої купи з безліччю вказівників звільнення пам’яті у відому мить перемагає будь-який трасувальний збирач.
Другий кейс — поправка до того, як зазвичай розповідають перший. У вересні 2022 року Cloudflare описала Pingora — власний HTTPHyperText Transfer Protocol — протокол вебуПротокол, яким спілкуються браузер і сервер: клієнт надсилає метод і адресу, сервер відповідає кодом стану й тілом. Між запитами він нічого не памʼятає — кожен запит стоїть сам по собі, тому все, що треба памʼятати, передається явно.Усі терміни-проксі на Rust, який замінив Nginx для трафіку до серверів-джерел і обслуговував понад трильйон запитів на день. Він споживав приблизно на 70% менше CPU і на 67% менше пам’яті, ніж старий сервіс, за того самого трафіку. Допис обережний щодо причин. Частина економії прийшла від того, що Rust замінив Lua; велика частина — від задуму: один багатопотоковий процес на Tokio зі спільним пулом з’єднань замість пулу на кожен робочий процес Nginx, — що скоротило нові з’єднання до серверів-джерел утричі. Аргумент про безпеку пам’яті окремий і простіший: після «кількох сотень трильйонів запитів» Pingora «ще жодного разу не впав через код нашого сервісу».
Четвертий кейс — найсильніший доказ на користь Rust, і він про новий код, а не про переписування. Команда Android у Google приблизно з 2019 року почала писати новий низькорівневий код мовами з безпечною пам’яттю, а наявний C і C++ лишила на місці. Опубліковані цифри показують результат: помилки безпеки пам’яті становили 76% вразливостей Android у 2019 році, 35% у 2022-му, 24% у 2024-му, а у 2025-му вперше — менш як 20%. Пояснення, яке дає команда, — вік коду: більшість помилок пам’яті живе в новому коді, тож зупинка їх біля джерела щороку зменшує частку, навіть коли старий код лишається. У листопаді 2025 року вони додали щільність: близько 0,2 вразливості безпеки пам’яті на мільйон рядків Rust проти приблизно 1000 на мільйон у їхньому C і C++. І дві цифри поставки, яких ніхто не чекав: зміни на Rust відкочували приблизно вчетверо рідше, а на рев’ю вони проводили приблизно на 25% менше часу.
П’ятий кейс — unwrap(), що панікою поклав парк проксі Cloudflare в листопаді 2025 року, — розказано в розділі про помилки й паніки. Прочитані разом, ці п’ять кейсів проводять ту саму межу, що й таблиця про те, чого компілятор перевірити не може: Rust повністю прибирає один клас помилок і лишає кожен інший клас рівно там, де він був.
Де вона вироджується
Гарантія Rust точна, а ціна сплачується наперед. Команда платить часом навчання й часом компіляції ще до першого релізу, а отримує натомість клас помилок, що ніколи не потрапляє в продакшн. Вона вироджується, коли гарантію читають ширше, ніж вона є, або коли ціну платять за задачу, якій вона не була потрібна:
unwrap()іexpect()на вводі, що справді може бути хибним, — і один поганий файл стає панікою всього парку..clone()усюди, щоб угамувати borrow checker, доки гарячий шлях не почне витрачати час на копіювання (рядок 1).- Павутина з
Rc<RefCell<…>>, що переносить кожну помилку позичання на час виконання й тече на циклах. - Блоки
unsafeбез коментаря// SAFETY:, без запуску Miri і з безпечним API, що їм довіряє. - Блокуючі виклики всередині async-задач, що зупиняють кожну задачу на тому самому потоці середовища.
- Віра, що сервіс на Rust не може мати вразливостей, — логіка, екранування, авторизація й конфігурація лишаються на вас.
- Переповнення цілих у релізних збірках, що тихо загортається там, де налагоджувальна збірка запанікувала б.
- Дерево залежностей із сотень крейтів, яке ніколи не перевіряли за RustSec.
- Час компіляції, якого ніхто не заклав у бюджет і який гальмує цикл зворотного зв’язку кожного інженера.
- Переписування робочого коду, обране заради мови, а не заради виміряної проблеми.
Чесна межа — відповідність задачі. Rust — найкращий доступний інструмент, коли безпека пам’яті й передбачувана латентність важать разом: проксі, рушій бази даних, компонент браузера, драйвер ядра, прошивка чи гарячий шлях, який постійно перериває збирач сміття. Для CRUD-сервісу, чий час іде на очікування бази даних, його гарантії захищають від помилок, яким Go, Java чи Python уже запобігають збирачем, і команда платить швидкістю змін за безпеку, яку вже мала. Урок Android ріже так само: виграш дало написання нового низькорівневого коду на Rust, а не переписування на ньому всього.
Практична перевірка займає десять хвилин. Запустіть rustc --version там, де збираєте, і прочитайте редакцію в Cargo.toml. Знайдіть на шляху запиту unwrap( і expect( і спитайте, який ввід ламає кожен. Порахуйте блоки unsafe і перевірте, що кожен має коментар SAFETY. Переконайтеся, що CI запускає Clippy і cargo audit. І пошукайте блокуючі виклики — std::fs, std::thread::sleep, синхронні клієнти — всередині async fn.
Коли це застосовувати
Застосовуйте, коли
- Інфраструктура, де безпека пам’яті й передбачувана латентність важать разом: проксі, бази даних, середовища виконання.
- Код, що на низькому рівні обробляє недовірений ввід: парсери, кодеки, мережеві протоколи.
- Сервіси з величезною довгоживучою купою, де проблемою є паузи збирача.
- Швидкі ядра бібліотек, які викликають з Python, Node чи C, де Rust заміняє C.
Уникайте, коли
- CRUD-сервіси, що здебільшого чекають на базу даних, — безпеку вам уже дає збирач.
- Команди з жорстким дедлайном і без досвіду Rust: крива навчання припадає на перші місяці.
- Прототипи, чия форма змінюється щотижня: компілятор робить кожну перебудову явною.
- Переписування стабільного робочого коду без виміряної проблеми, яку це переписування розв’язує.
Джерела й метод
На чому стоїть ця стаття
- 17 джерел
- 2 задокументовані збої
- Перевірено 13 жовтня 2026 р.
Практики й походження термінів
дванадцять помилок компілятора, володіння, конкурентність і unsafe- ГайдThe Rust Programming Language — Understanding Ownership (відкривається в новій вкладці)doc.rust-lang.org
- ГайдThe Rust Programming Language — Fearless Concurrency (відкривається в новій вкладці)doc.rust-lang.org
- ГайдThe Rust Programming Language — Unsafe Rust (відкривається в новій вкладці)doc.rust-lang.org
- СтандартThe Rust Reference (відкривається в новій вкладці)doc.rust-lang.org
- ДокументаціяRust error codes index (відкривається в новій вкладці)doc.rust-lang.org
- ГайдThe Rust Edition Guide (відкривається в новій вкладці)doc.rust-lang.org
- ГайдThe Cargo Book (відкривається в новій вкладці)doc.rust-lang.org
- Документаціяtokio::task::spawn_blocking (відкривається в новій вкладці)docs.rs
- СтаттяAnnouncing Rust 1.0 (відкривається в новій вкладці)Rust Blog · 15.05.2015
Збої, на яких вчиться стаття
BatBadBut і збій Cloudflare у листопаді 2025 у «П’ять кейсів»Дослідження
Discord, Pingora, Android і Linux: що виміряв перехід- СтаттяJesse Howarth — Why Discord is switching from Go to Rust (відкривається в новій вкладці)Discord · 04.02.2020
- СтаттяYuchen Wu, Andrew Hauck — How we built Pingora, the proxy that connects Cloudflare to the Internet (відкривається в новій вкладці)Cloudflare · 14.09.2022
- ДослідженняMemory Safe Languages in Android 13 (відкривається в новій вкладці)Google Online Security Blog · 01.12.2022
- ДослідженняEliminating Memory Safety Vulnerabilities at the Source (відкривається в новій вкладці)Google Online Security Blog · 25.09.2024
- ДослідженняJeff Vander Stoep — Rust in Android: move fast and fix things (відкривається в новій вкладці)Google · 13.11.2025
- СтаттяThe (successful) end of the kernel Rust experiment (відкривається в новій вкладці)LWN.net · 12.2025
Дослідження з Claude. Пошук і звірку першоджерел зроблено з Claude (Anthropic). Відбір, текст і перевірку фактів — редакція Anatomy of IT Product.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.