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

Тема
Описание
Доп.

В резюме следует донести информацию:

  • что вы понимаете как устроены бизнес-процессы вы умеете общаться и адекватны
  • умеете решать задачи, есть навыки и опыт решения проблем
  • вы ответственный человек, планируете сроки ...

STAR — это аббревиатура от четырех ключевых элементов для подготовки к собеседованию и формулировки опыта в резюме:

  • Situation (Ситуация)
  • Task (Задача)
  • Action (Действие)
  • Result (Результат)

Блок: О себе:

  1. Общее интро о себе
  2. Философия, стэк или релевантные профессии, хобби
  3. Контакты

Вопросы для Rust разработчика

Rust

  • Рассказать про статическую и динамическую диспетчеризации.
  • Что такое мономорфизация?
  • Какие гарантии даёт safe код?
  • Как устроена обработка ошибок?
  • Как rust помогает писать многопоточный код?
  • Почему RwLock требует T: Send + Sync, а Mutex только T: Send?
  • Что даёт repr(C) атрибут структуры? А enum?
  • Зачем нужны ZST?
  • Ковариантность и контравариантность?
  • Как устроен Trait Object? Отличие от устройства объектов в С++.
  • Как устроен Box? Vec? Rc/Arc?
  • Плюсы и минусы типажей в сравнении с классами/интерфейсами в ООП языках.
  • Associated types vs generic types?
  • Что означает 'static в разных контекстах? (например, thread::spawn)
  • Для любого ли типажа можно создать trait object? Object safety.
  • Orphan rules.
  • Что такое move semantics?
  • Как устроен async await?
  • Буферизация I/O.
  • Чем отличается указатель от ссылки?
  • Что такое RAII?
  • &str vs String
  • lifetimes
  • Cow, Cell,
  • stack/heap
  • Copy/Clone
  • smart pointers

Алгоритмы и структуры данных

  • Что такое big-O нотация?
  • Что такое двоичная куча?
  • Как устроены хеш-таблицы? Требования к ключам в hashmap.
  • Как устроены B-деревья? Требования к ключам в btreemap.
  • Что такое фильтр Блума? (как вариант: cuckoo фильтр)
  • Что такое LRU кеш и как его сделать?
  • Какие сортировки знаешь, как они работает, какая сложность?
  • Обход графов в глубину / в ширину.
  • Нахождение кратчайшего пути в графе, алгоритм Дейкстры.
  • Lock-free, wait-free структуры данных. Skipmap.
  • Устройство spsc, spmc, mpsc, mpmc очередей.

Многозадачность

  • Что такое многозадачность?
  • Чем кооперативная многозадачность отличается от вытесняющей?
  • Что такое зелёные потоки? Чем отличаются stackful и stakless корутины?
  • Какая разница между параллельностью и concurrency?
  • Когда использовать потоки, а когда событийный цикл?
  • Что такое мультиплексирование?
  • Как устроены событийные циклы (libuv, tokio)?
  • Примитивы синхронизации: mutex, семафоры.

Linux

  • Что такое виртуальная память?
  • Чем стек отличается от кучи?
  • Чем процесс отличается от потока?
  • Что такое load average? LA=8 это много или мало?
  • Что такое своп и зачем он нужен?
  • Что такое прерывание? Верхняя и нижняя половины прерывания.
  • Когда и как работает планировщик задач?
  • Какие способы организовать IPC ты знаешь?

Процессоры

  • Что такое кэш процессора, зачем нужен?
  • Механизмы когерентности кэшей.
  • Что такое вычислительный конвейер?
  • Что такое суперскалярность?
  • Что такое TLB?

Сеть

  • Разница между моделью TCP/IP и моделью OSI.
  • В чем разница между TCP и UDP?
  • Что такое MTU?
  • Как сделать UDP надёжным (убрать дубликаты, гарантировать доставку)?
  • Какая разница между балансированием на L3, L4 и L7?
  • Что такое RPC? Что такое REST? RPC vs REST.
  • Long-polling vs streaming? (как вариант: pull vs push).

Базы данных

  • OLAP vs OLTP.
  • Колоночные vs строковые.
  • SQL vs NoSQL.
  • Что такое индексы и как они реализуются?
  • Что такое LSM-дерево?
  • Что такое транзакция?
  • Что такое ACID?
  • Что такое теорема CAP?
  • Разница между at (least|most|exactly) once семантиками доставки сообщений?
  • Разница между 0, 1, 5 и 10 рейдами? Что такое диск четности?

Трансляторы

  • Разница между компилятором и интерпретатором?
  • Что такое ABI?
  • Что такое AST?
  • Что такое JIT компиляция?
  • Из чего состоит компилятор? (лексер, парсер, семантер, генератор)
  • Что такое IR?

Криптография

  • Что такое симметричное шифрование и где применяется?
  • Что такое асимметричное шифрование и где применяется?
  • Что такое хэширование и коллизии?
  • Как устроен блокчейн? Биткоин? Эфир?

Описание языка Rust

безопасность, скорость и параллелизм

Rust — статически типизированный это системный язык программирования с безопасностью на уровне типов (Null Safety, Borrow checker, Send и Sync безопасная работа с потоками), управлением памятью без сборщика мусора, нулевыми накладными расходами на абстракции, поддержкой многопоточности без гонок данных и современными функциональными возможностями.

статически типизированный - Типы переменных и функций определяются во время компиляции, а не в рантайме.

системного уровня - Позволяет работать с низкоуровневыми деталями, такими как память через указатели (&T, *const T, *mut T), управление ресурсами, и при этом без виртуальной машины или GC, максимально близко к железу, без скрытых аллокаций. Компилируется в нативный машинный код (через LLVM), без интерпретатора и VM.

LLVM

LLVM (Low Level Virtual Machine) — это инфраструктура компилятора, на которой основан компилятор Rust. Rust использует LLVM для преобразования своего промежуточного представления (IR) в машинный код, что позволяет добиться высокой производительности и портативности.

Проект Rust-GCC предоставляет возможность компиляции Rust-кода с использованием GCC. Это позволяет разработчикам использовать преимущества GCC в тех случаях, когда LLVM не подходит или недоступен. Использование GCC может быть выгодно для проектов, которые уже активно используют этот компилятор и его инструменты.

Таким образом, Rust-GCC предоставляет альтернативный способ компиляции Rust-кода, что увеличивает гибкость и возможности для разработчиков.

При сборке программы Rust компилятор Rust (Rustc) создает байт-код Rust и передает его другому компилятору, называемому LLVM, для создания машинного кода (LLVM также используется такими языками, как Swift и Scala, и преобразует байт-код, созданный компилятором языка, в машинный код для запуска операционной системы). Это означает, что Rust можно скомпилировать в любой операционной системе, поддерживаемой LLVM.

парадигма функционального стиля - Поддерживает концепции функционального программирования: функции как значения, map/filter/reduce, замыкания, иммутабельность по умолчанию.

жаргон функционального программирования в Rust

примеры функциональной парадигмы
fn main(){
   // Замыкания (closures):
   let add = |x, y| x + y;
   println!("{}", add(2, 3));

   // map, filter, fold для итераторов:
   let sum: i32 = (1..5).map(|x| x * 2).sum();

  // Чистые функции
  fn sum(a: usize, b: usize) -> usize {
      return a + b;
  }

// Композиция функций
// Функция-композитор: принимает две функции и возвращает новую
 fn compose<F, G>(f: F, g: G) -> impl Fn(i32) -> i32
   where
      F: Fn(i32) -> i32,
      G: Fn(i32) -> i32 {
    move |x| f(g(x))
 }
}

Функции высшего порядка - это функции, которые принимают другие функции в качестве аргументов или возвращают функции в качестве результата.

fn add(x: usize) -> usize {
     // это печатается, поскольку функции оцениваются первыми
     println!("executing add"); 
     return x + x;
}
fn multiply(x: usize) -> usize {
     // это печатается, поскольку функции оцениваются первыми
     println!("executing multiply"); 
     return x * x;
}
type FnType = fn(t: usize) -> usize;

// Теперь это функция высшего порядка, поэтому оценка функций задерживается в if-else
fn add_or_multiply(add: bool, on_add: FnType, on_multiply: FnType, t: usize) -> usize {
     if add {
         on_add(t)
     } else {
         on_multiply(t)
     }
}
fn main(){
    println!("{}", add_or_multiply(true, add, multiply, 4)); // 8
    println!("{}", add_or_multiply(false, add, multiply, 4)); // 16
}

Рекурсия - это процесс, при котором функция вызывает саму себя.

fn main() {
    fn factorial(num: usize) -> usize {
        return match num {
            0 => 1,
            _ => num * factorial(num - 1),
        };
    }

    println!("{}", factorial(20)); // 2432902008176640000
}

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

fn add(x: i32) -> impl Fn(i32) -> i32 {
    move |y| x + y
}
fn main(){
    let add5 = add(5); // функция, которая прибавляет 5
    println!("{}", add5(3)); // 8
}

парадигма процедурного (императивного) стиля - Поддерживает традиционные конструкции императивных языков (циклы, условия, переменные, изменяемое состояние).


1. Безопасный по памяти (memory safe) без сборщика мусора

Rust гарантирует отсутствие ошибок управления памятью (use-after-free, double free, data race) на этапе компиляции без GC. Это достигается через систему владения (ownership) и заимствований (borrowing).

Указатели можно использовать только в небезопасном коде (unsafe), в безопасном коде применяются исключительно ссылки на гарантированно существующие объекты.

2. Zero-cost abstractions Rust даёт высокоуровневые конструкции (итераторы, замыкания, async) без потерь производительности по сравнению с ручным кодом на C. Всё инлайнится и оптимизируется. Генерируется машинный код без лишних прослоек.

Отсутствует проверка доступа к недействительным данным invalid data access во время выполнения, так как это делается один раз в момент компиляции.

3. Concurrency без гонок данных Rust гарантирует потокобезопасность на уровне типов: Data race невозможен, потому что borrowing проверяется компилятором. Параллелизм безопасен без runtime-оверхода.


Rust хорошо подходит для FFI с C

  • Rust и C оба работают с нативной памятью без виртуальной машины и сборщика мусора.

  • Rust не добавляет скрытых прослоек (нет GC, нет рефлекшена), поэтому данные можно передавать напрямую.

  • Типы вроде i32, f64, mut T в Rust соответствуют типам в C (int32_t, double, void).

  • Миллионы библиотек (OpenSSL, SQLite, zlib) можно подключить в Rust без переписывания.

  • Производительность без оверхеда. FFI между Rust и C = прямые вызовы функций (без маршаллинга как в Java/C#). Практически нулевой overhead.

  • Можно внедрять Rust в C-проекты постепенно: Пишем новую часть на Rust. Экспортируем её в виде C API. Подключаем к старому коду.

  • Совместимость с системами и драйверами. Rust легко пишет драйверы, ОС, системные утилиты, где всё API на C.


Три основных инструмента command_line

  • Cargo, который управляет целым ящиком
  • rustup, который управляет установками Rust
  • rustc, который управляет компиляцией исходного кода Rust.
  • rust-analyzer - расширение для vscode для подсветки и вывода типов

1. Системная разработка (System Programming)

Rust изначально задумывался как замена C/C++ для низкоуровневых задач, где важны производительность и безопасность.

Что делают на Rust в этой области:
  • Ядра и ОС:

    • Rust включён в ядро Linux (поддержка модулей и драйверов).
    • Redox OS — операционная система полностью на Rust.
  • Embedded:

    • Rust работает без стандартной библиотеки (#![no_std]), подходит для микроконтроллеров.
    • Примеры: IoT, bare-metal прошивки.
  • Базы данных:

    • SurrealDB, TiKV — высокопроизводительные и безопасные СУБД.
  • Системы виртуализации и контейнеры:

    • Firecracker (AWS), Cloud Hypervisor.
  • Компиляторы и туллинг:

    • Rustc (сам компилятор Rust).
    • Линтеры: Clippy.
    • Редакторы: Lapce, Helix.
    • Парсеры, форматтеры: rustfmt, tree-sitter.

Почему Rust здесь подходит:

  • Безопасность на уровне типов → меньше багов, чем на C.
  • Нет GC → предсказуемая работа.
  • Производительность на уровне C.

2. Прикладное ПО (Desktop Applications)

Rust всё чаще используется для графических и CLI-приложений

Что делают на Rust в этой области:
  • Безопасность.
  • Кроссплатформенность (Linux, Windows, macOS).
  • Высокая производительность.

Примеры:

  • Lapce, Helix — текстовые редакторы.

  • Alacritty — быстрый терминал.

  • Zellij — терминальный мультиплексор.

  • Ripgrep, fd — быстрые CLI-инструменты.

  • Графические интерфейсы:

    • Tauri (альтернатива Electron, но лёгкая).
    • Dioxus (React-подобный UI-фреймворк).

3. Backend-разработка

Rust стал популярным для высоконагруженных сервисов и микросервисов, где важны:

Что делают на Rust в этой области:
  • Предсказуемая производительность.
  • Низкая задержка.
  • Безопасность.

Примеры:

  • Веб-фреймворки:

    • Actix Web (самый быстрый веб-фреймворк на Rust).
    • Axum, Warp.
  • Асинхронность:

    • Tokio (асинхронный runtime).
  • Компании:

    • Discord переписал часть backend на Rust для экономии CPU.
    • Amazon, Cloudflare используют Rust в продакшене.

4. Blockchain и криптоиндустрия

Rust стал стандартом де-факто в блокчейн-разработке:

Что делают на Rust в этой области:
  • Безопасность без GC.
  • Производительность.
  • Сложная логика смарт-контрактов → нужна строгая типизация.

Примеры:

  • Solana — смарт-контракты на Rust.
  • Polkadot — на Rust.
  • Near Protocol — на Rust.
  • Substrate (фреймворк для блокчейнов).

5. GameDev

Движки на Rust (Bevy, Amethyst).

6. Machine Learning / Data Science

Пока не доминирует, но есть проекты (Burn, Polars).

7. WebAssembly

Rust идеально подходит для WASM (игры, фронтенд-библиотеки, расширения браузеров).

Rust – один из лучших языков для компиляции в WebAssembly. Wasm позволяет запускать код с производительностью, близкой к нативной, прямо в веб-браузере (или на сервере с Wasm-рантаймом). Это позволяет переносить сложные вычисления или целые приложения в веб без необходимости писать их на JavaScript:

  • Высокопроизводительные веб-приложения.
  • Игры в браузере.
  • Криптография, обработка изображений/видео прямо в браузере.

Почему Rust?

Удобная экосистема - единый компилятор от разработчиков Rust со встроенным менеджером и сборщиком пакетов (cargo), системой тестов и генератором документации. Отличная документация, туториалы, библиотеки, сообщество.


Каких ошибок помогает избежать

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

1. Memory Safety (Ошибки управления памятью)

В C/C++:

  • Use-after-free (использование после освобождения памяти)
  • Double free (двойное освобождение)
  • Dangling pointers (висячие указатели - живые ссылки на данные, которые стали недействительными в ходе работы программы)
  • Memory leak (утечки памяти)
  • Buffer overflow (выход за границы массива, переполнение буфера - попытка получить доступ к 12-му элементу массива всего с 6 элементами)

В Rust:

  • Невозможно по определению из-за владения (ownership) и заимствований (borrowing):
fn main(){
  let x = String::from("Hello");
  let y = x;  // x перемещён, теперь нельзя использовать x
  println!("{}", x); // ❌ ошибка компиляции
}

2. Data Race в многопоточности (гонки данных)

В C++/Go/Java:

  • Возможны гонки данных при доступе к одной переменной из разных потоков.
  • Гонки данных - невозможность определить, как программа будет вести себя от запуска к запуску, из-за изменения внешних факторов.

В Rust:

  • Гарантия на уровне типов:

    • Либо несколько иммутабельных ссылок, либо одна мутабельная.
    • Send/Sync трейты проверяют, что тип можно передавать между потоками.
fn main(){
    let mut x = 0;
    let r1 = &x;
    let r2 = &mut x; // ❌ ошибка компиляции
}

3. Null / NPE (Null Pointer Exception)

В Java/C++:

  • Легко получить NullPointerException или dereference null.

В Rust:

  • Нет null вообще.
  • Используется Option<T>:
fn main(){
  let x: Option<i32> = None;
  println!("{}", x.unwrap()); // ❌ компилятор заставит обработать None
}

4. Dangling references

В C++:

  • Возвращение ссылки на локальную переменную → UB.

В Rust:

  • Borrow checker запрещает:
fn get_ref() -> &String {
     let s = String::from("Hi");
     &s // ❌ ошибка компиляции
}

5. Типовые ошибки и несоответствие контрактов

  • Rust имеет сильную систему типов:

    • Нет неявных преобразований (например, i32u32 нужно явно).
    • Generic с ограничениями через трейты (T: Trait), вместо неявных допущений как в C++ templates.

6. Iterator invalidation (Недействительность итератора)

Недействительность итератора - проблема, вызванная чем-то, что повторяется после изменения в середине

В C++:

  • Можно удалить элемент из контейнера и продолжить итерацию → UB.

В Rust:

  • Итераторы работают с владением:
fn main(){
  let mut v = vec![1, 2, 3];
  for i in v.iter() {
      v.push(4); // ❌ ошибка компиляции (mutable + immutable borrow)
  }
}

7. Безопасность FFI

  • Rust заставляет обозначать небезопасные зоны (unsafe {}) при работе с C:
  extern "C" { fn some_c_func(); }
  unsafe { some_c_func(); } // явно помечено

8. Dangling thread handles

В других языках можно "забыть" join поток, Rust:

  • Поток не может быть уничтожен без join или detach, иначе ошибка компиляции.

9. Строковые ошибки

  • Нет невалидных UTF-8 строк в String (в отличие от C++ std::string).
  • Все строки — валидный UTF-8.

10. Случайные runtime ошибки GC

  • В Java/C#: GC может неожиданно задержать поток.
  • В Rust: нет GC → предсказуемая работа в реальном времени.

Итог: Rust устраняет

  • UB (Undefined Behavior) → практически невозможно в safe-коде.
  • Null/NPE.
  • Data races.
  • Dangling pointers.
  • Buffer overflow (в safe-коде).
  • Use-after-free.
  • Double free.
  • Iterator invalidation.
  • Ошибки многопоточности на уровне типов.

Трудные инструменты написания процедурных макросов

Нет Типов высшего порядка HKT

Нет Врядик дженериков (для функций с произвольным количеством аргументов)

Нет Type alias imp trait (т.е. Existential Types)

(экзистенциальные типы похожи на шаблоны, а именно тем, что заранее конкретный тип объекта не определен.

Важнее понять главное отличие экзистенциальных типов от шаблонов:

  • Generics определяет объект по четким ограничениям типов.
  • Existential определяет объект по его свойствам.)

Нет Ревевантных (линейных) типов


Нет возможностей Erlang

  • Высокий uptime (High Uptime) - Способность системы работать непрерывно в течение очень длительного времени
  • Fault-tolerant системы (Отказоустойчивые системы) - Системы, которые могут продолжать работать даже при возникновении сбоев в отдельных их компонентах.

Нет возможностей Lisp

Rust-макросы работают на синтаксическом уровне AST, но не могут менять семантику языка или определять новые правила компиляции. Макросы ограничены грамматикой Rust. Макросы разворачиваются до проверки типов, но компилятор проверяет итоговый код.

Макросы в Lisp — это часть языка, работающая на уровне исходного кода в виде данных. Код = данные (homoiconicity) → макросы могут создавать новые конструкции языка.

В Lisp Можно:

  • Создавать новые синтаксические формы. Можно написать макрос, который меняет язык до неузнаваемости.
  • Определять собственные управляющие структуры (loop, unless, match) прямо в языке. Ошибки макросов могут появиться в runtime, если макрос генерирует некорректный код. Нет строгой статической проверки.
# install Rust
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ rust install

# установить конкретную версию
$ rustup install 1.30.0
$ rustup install nightly-2018-08-01
$ rustup install stable
$ rustup install beta
$ rustup install nightly

$ rustup -V
$ rustc --version
$ rustup --version
$ cargo --version

# установка рядом nightly
$ rustup toolchain install nightly

# обновить версии
$ rustup update
$ rustup update nightly

# обновить версию и почистить кеш
$ rustup update
$ cargo install cargo-cache --force
$ rm -rf target/
$ cargo cache -e
$ make test.unit

# обновить до stable
$ rustup update stable
   stable-x86_64-unknown-linux-gnu unchanged - rustc 1.54.0 (a178d0322 2021-07-26)
   nightly-x86_64-unknown-linux-gnu unchanged - rustc 1.56.0-nightly (2827db2b1 2021-08-01)

# удалить
$ rustup uninstall
$ rustup self uninstall
# запуск nightly
$ rustup run nightly cargo build 
$ rustup run nightly cargo run --bin lessons

# псевдоним запуск nightly
$ cargo +nightly build

# запуск nightly по умолчанию для проекта
$ cd ~/projects/needs-nightly
$ rustup override set nightly

# всегда запускать версию по умолчанию:
$ rustup default nightly
$ rustup default stable

install, remove, show target

add component

# показывает все возможные цели компиляции (targets), которые поддерживает установленная версия Rust, и статус для каждой.
$ rustup target list

# install target:
$ rustup target add x86_64-unknown-linux-gnu
$ rustup target add thumbv7m-none-eabi
$ rustup target add wasm32-unknown-unknown
$ rustup target add wasm32-unknown-unknown --toolchain nightly

# удалить target
$ rustup target remove wasm32-unknown-unknown

# установить компонеты
$ rustup component add rustfmt --toolchain nightly-x86_64-unknown-linux-gnu
$ rustup component add clippy --toolchain stable-x86_64-unknown-linux-gnu

# show targets:
$ rustup component list --installed

# Показывает текущую конфигурацию rustup 
## Активный toolchain (stable, beta, nightly)
## Где установлен Rust
## Какие компоненты активны (rustc, cargo, clippy, rustfmt)
## Какие targets установлены
$ rustup show

$ rustc --version --verbose
$ rustup show
Default host: x86_64-unknown-linux-gnu
rustup home:  /home/jeka/.rustup

x86_64-unknown-linux-gnu которая включает 
архитектуру процессора (x86_64)
производителя (unknown),
операционную систему (linux) 
ABI (gnu)


installed toolchains
------------------- 

stable-x86_64-unknown-linux-gnu (default)
nightly-x86_64-unknown-linux-gnu

installed targets for active toolchain
------------------- 

thumbv7m-none-eabi
wasm32-unknown-unknown
x86_64-unknown-linux-gnu

active toolchain
------------------- 

stable-x86_64-unknown-linux-gnu (default)
rustc 1.72.0 (5680fa18f 2023-08-23)
# Управление версиями
# Чтобы установить набор инструментов по умолчанию на что-то кроме stable:
$ rustup toolchain default nightly

# Чтобы использовать цепочку инструментов, отличную от стандартной, используйте rustup run:
$ rustup run nightly cargo build

# Есть также псевдоним для этого, который немного короче:
$ cargo +nightly build

#Если вы хотите использовать другой каталог по умолчанию, это тоже просто! 
# Если вы запустите это внутри проекта:
$ rustup override set nightly

# Или, если вы хотите настроить таргетинг на другую версию Rust:
$ rustup override set 1.30.0

Nightly

Nightly

# проверим, что ночной набор инструментов был успешно установлен
rustup toolchain list | grep nightly / rust toolchain  файл для фиксации версии компилятора

# Установка точной версии
$ rustup install nightly-<yyyy-MM-dd>

# Переход на более раннюю версию Rust Nightly
$ rustup uninstall nightly
$ rustup install nightly-<yyyy-MM-dd>
$ rustup target add wasm32-unknown-unknown --toolchain nightly-<yyyy-MM-dd>

Проверка установленных toolchain в системе:

$ rustup toolchain list

    stable-x86_64-unknown-linux-gnu (active, default)
    nightly-x86_64-unknown-linux-gnu


# Переключиться на nightly
$ rustup override set nightly

# Переключиться на stable 
$ rustup override set stable

Или создать в проекте файл rust-toolchain.toml:

[toolchain]
channel = "nightly"
components = ["rustfmt", "clippy"]
targets = ["x86_64-unknown-linux-gnu"]

Можно еще точнее, установить конкретную версию, чтобы сборка не ломалась из-за обновлений nightly:

rustup toolchain install nightly-2025-01-10

Файл rust-toolchain.toml:

[toolchain]
channel = "nightly-2025-01-10"
components = ["rustfmt", "clippy"]
targets = ["x86_64-unknown-linux-gnu"]
  • При входе в каталог проекта rustup автоматически переключится на nightly
  • cargo build, cargo run, rustc будут использовать nightly
  • Версия фиксируется на уровне проекта, а не глобально