Перейти к содержимому

Ошибка Rust E0554: #![feature] may not be used on the stable release channel

E0554 значит: твой код начинается со строки #![feature(...)], а такие строки принимает только nightly-версия Rust. Почти всегда эта ошибка приходит вместе со скопированным кодом: из статьи, репозитория на GitHub, ответа ИИ или старого ответа на Stack Overflow. Тот код писали для nightly Rust, а у тебя stable — именно его rustup устанавливает по умолчанию. С твоей установкой всё в порядке. Обычно исправление — удалить одну строку и сделать то же самое стабильным способом. (Эта страница входит в раздел Ошибки компилятора Rust с объяснениями.)

error[E0554]: `#![feature]` may not be used on the stable release channel
--> src/main.rs:1:1
|
1 | #![feature(iter_map_windows)] // ❌ copied from code written for nightly Rust
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

По-русски: «#![feature] нельзя использовать в стабильном канале выпусков».

Вот программа, которая её вызывает (комментарий // ❌ оставлен на английском, потому что rustc цитирует эту строку; он значит «скопировано из кода, написанного для nightly Rust»):

#![feature(iter_map_windows)] // ❌ copied from code written for nightly Rust
fn main() {
let temps = [18, 21, 19, 24];
let changes: Vec<i32> = temps.iter().map_windows(|[a, b]| *b - *a).collect();
println!("{:?}", changes);
}

^^^ подчёркивает всю первую строку, #![feature(iter_map_windows)]. Эта строка — просьба: «пожалуйста, включи недоделанную возможность под названием iter_map_windows». Такие просьбы принимает только компилятор nightly. «Stable release channel» («стабильный канал выпусков») в сообщении — это обычный Rust, который ставит rustup, и он отказывается.

Обрати внимание, на что rustc не жалуется: на map_windows в строке 5. Он останавливается на строке #![feature] раньше. Только когда ты её удалишь, станет понятно, работает ли остальной код на stable.

Ту же ошибку ты получишь и в канале beta. Если в коде несколько строк #![feature], rustc обычно сообщает только о первой, так что проверь начало файла — там могут быть ещё.

Это как пропуск «только для персонала». На тестовую кухню (nightly) с ним пустят. А ресторан (stable) такие пропуска не принимает вообще, как вежливо его ни показывай.

Rust обещает, что код, который компилируется на stable сегодня, будет компилироваться на каждом будущем стабильном выпуске 1.x. Недоделанные возможности не могут входить в это обещание: их имена, аргументы и поведение ещё могут измениться, а сами они могут исчезнуть. Поэтому они живут только в nightly — новой сборке компилятора, которую делают каждую ночь, — и каждую из них включают по имени через #![feature(...)].

Стабильный Rust не просто игнорирует эту строку, а останавливается с ошибкой. Так ты не сможешь незаметно построить проект на недоделанной возможности. Когда возможность готова, она становится частью стабильного Rust, и строка для неё больше не нужна.

Поэтому, увидев E0554, стоит задать себе всего три вопроса: есть ли стабильный способ это сделать (исправление 1), стала ли возможность уже стабильной (исправление 2) и действительно ли тебе нужен nightly (исправление 3)? Подробнее — в разделе Stable, beta и nightly.

Исправление 1: Убери атрибут и используй стабильный API

Заголовок раздела «Исправление 1: Убери атрибут и используй стабильный API»

Это нужно почти всегда. Удали строку #![feature] и скомпилируй снова. Если теперь получишь E0658 (use of unstable library feature `iter_map_windows` ), значит, возможность всё ещё не доделана и нужен стабильный способ сделать то же самое. Большинство нестабильных методов — сокращения для того, что стабильный Rust уже умеет. Здесь .windows(2) у среза даёт каждую пару соседей:

fn main() {
let temps = [18, 21, 19, 24];
let changes: Vec<i32> = temps.windows(2).map(|w| w[1] - w[0]).collect(); // ✅ стабильно
println!("{:?}", changes);
for w in temps.windows(2) {
println!("{} -> {}", w[0], w[1]);
}
}

Вывод:

[3, -2, 5]
18 -> 21
21 -> 19
19 -> 24
▶ Попробуй сам

Чтобы найти стабильный способ, открой метод в документации стандартной библиотеки. У нестабильных элементов есть плашка «This is a nightly-only experimental API», а имя возможности из строки #![feature] обычно совпадает со страницей в The Unstable Book (на английском). Подробнее — в уроках Срезы и Итераторы.

Исправление 2: Проверь, не стала ли возможность стабильной

Заголовок раздела «Исправление 2: Проверь, не стала ли возможность стабильной»

Выбирай этот вариант, когда код немного старый. Многие возможности, которым когда-то нужен был #![feature], теперь входят в стабильный Rust, и тогда строка просто больше не нужна. rustc сообщает об этом в предупреждении прямо под ошибкой:

error[E0554]: `#![feature]` may not be used on the stable release channel
--> src/main.rs:2:1
|
2 | #![feature(slice_as_chunks)] // ❌ not needed any more: this feature is stable now
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: the feature `slice_as_chunks` has been stable since 1.88.0 and no longer requires an attribute to enable
--> src/main.rs:2:12
|
2 | #![feature(slice_as_chunks)] // ❌ not needed any more: this feature is stable now
| ^^^^^^^^^^^^^^^

Предупреждение говорит: «возможность slice_as_chunks стабильна с версии 1.88.0, и атрибут для её включения больше не нужен». Программа с ошибкой (комментарий // ❌ значит «больше не нужно: эта возможность теперь стабильна»):

// Скопировано из старого учебника
#![feature(slice_as_chunks)] // ❌ not needed any more: this feature is stable now
fn main() {
let pixels = [255, 0, 0, 0, 128, 255];
let (rgb, _rest) = pixels.as_chunks::<3>();
for [r, g, b] in rgb {
println!("r={} g={} b={}", r, g, b);
}
}

Удали строку #![feature] (и комментарий над ней), и остальное заработает без изменений:

fn main() {
let pixels = [255, 0, 0, 0, 128, 255];
let (rgb, _rest) = pixels.as_chunks::<3>(); // ✅ стабильно с Rust 1.88
for [r, g, b] in rgb {
println!("r={} g={} b={}", r, g, b);
}
}

Вывод:

r=255 g=0 b=0
r=0 g=128 b=255
▶ Попробуй сам

Для возможностей языка rustc ещё прямолинейнее: под ошибкой он добавляет help: remove the attribute («удали атрибут») и строку вроде the feature `async_closure` has been stable since `1.85.0` and no longer requires an attribute to enable.

Предупреждения нет, но ты подозреваешь, что возможность стабильна? Возможно, твой Rust просто старше версии, в которой она стала стабильной. Проверь и обнови:

Terminal window
rustc --version
rustup update

Если после этого rustc --version всё ещё показывает старую версию, скорее всего, в проекте есть файл rust-toolchain.toml, который её закрепляет. Подробнее — в разделе Закрепляем тулчейн для проекта.

Выбирай этот вариант в последнюю очередь — когда стабильного способа нет и ты согласен, что код может сломаться на будущем nightly. Типичные хорошие причины: ты пробуешь новую возможность, пишешь небольшой эксперимент или проект, в который ты вносишь вклад, уже использует nightly. Установи nightly рядом со stable и используй его для одной команды:

Terminal window
rustup toolchain install nightly
cargo +nightly run

Или переведи на nightly весь проект с помощью файла rust-toolchain.toml рядом с Cargo.toml. Тогда обычный cargo run в этой папке выберет nightly, а везде остальном — stable:

[toolchain]
channel = "nightly"

Если проект собирают и другие люди, закрепи дату, например channel = "nightly-2026-10-01", чтобы у всех был один и тот же компилятор. В Rust Playground выбери Nightly в меню тулчейна.

Тебе может попасться совет выставить RUSTC_BOOTSTRAP=1, чтобы stable принимал #![feature]. Этот переключатель существует для сборки самого компилятора Rust. С ним ты получаешь все риски nightly, делая вид, что сидишь на stable, — так что не надо.

Бенчмарки с #[bench]. Старые руководства пишут бенчмарки так, а #![feature(test)] до сих пор работает только в nightly:

error[E0554]: `#![feature]` may not be used on the stable release channel
--> src/main.rs:3:1
|
3 | #![feature(test)] // ❌ built-in benchmarks are nightly-only
| ^^^^^^^^^^^^^^^^^
//! Помощники для цен.
//! Бенчмарк написан по-старому, для nightly Rust.
#![feature(test)] // ❌ built-in benchmarks are nightly-only
extern crate test;
fn total(prices: &[u32]) -> u32 {
prices.iter().sum()
}
#[bench]
fn bench_total(b: &mut test::Bencher) {
let prices: Vec<u32> = (1..1000).collect();
b.iter(|| total(&prices));
}
fn main() {
println!("{}", total(&[3, 4, 5]));
}

Комментарий // ❌ значит «встроенные бенчмарки — только для nightly». Исправление: используй крейт для бенчмарков, который работает на stable, например criterion или divan, и запускай cargo bench. Удалить только строку #![feature] здесь недостаточно: тогда extern crate test; даст E0658 (use of unstable library feature `test` ). Подробнее — в уроке Производительность.

Зависимость, которой нужен nightly. Если строка --> указывает в крейт внутри ~/.cargo/registry/, а не в твой src/, значит, #![feature] использует крейт, от которого ты зависишь. Исправление: загляни в README крейта; часто более новая версия работает на stable (например, веб-фреймворку Rocket до версии 0.4 нужен был nightly, а 0.5 работает на stable). Иначе выбери другой крейт. Подробнее — в уроке Cargo и крейты.

Скопированный код с #![feature(let_chains)]. Цепочки let (if let Some(x) = a && x > 0) стали стабильными в Rust 1.88, но только в редакции 2024. Исправление: удали строку (исправление 2) и укажи edition = "2024" в Cargo.toml. Без этого получишь let chains are only allowed in Rust 2024 or later.

Проверь себя

1. Ты вставляешь код, который начинается с #![feature(try_blocks)], и получаешь E0554. Что это значит?

2. Под ошибкой rustc предупреждает, что возможность стабильна с версии 1.88.0. Что делать?

3. Тебе действительно нужен nightly для одного эксперимента. Какой способ самый чистый?

Результат: 0 / 3