Pular para o conteúdo

Erro E0554 do Rust: #![feature] may not be used on the stable release channel

O E0554 quer dizer que o seu código começa com uma linha #![feature(...)], e só a versão nightly do Rust aceita essas linhas. Quase sempre ele aparece em código copiado: de um post de blog, de um repositório no GitHub, de uma resposta de IA, de uma resposta antiga no Stack Overflow. Esse código foi escrito para o Rust nightly, e você está no stable, que é o que o rustup instala por padrão. Não tem nada de errado com a sua instalação. A correção costuma ser apagar uma linha e usar um jeito stable de fazer a mesma coisa. Esta página faz parte do guia de erros do compilador.

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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Em português: “#![feature] não pode ser usado no canal de lançamento stable”.

Este é o programa que gera o erro:

#![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);
}

(O comentário quer dizer “copiado de um código escrito para o Rust nightly”. Ele fica em inglês porque aparece na saída do compilador.)

O ^^^ sublinha a primeira linha inteira, #![feature(iter_map_windows)]. Essa linha é um pedido: “por favor, ative o recurso inacabado chamado iter_map_windows”. Só o compilador nightly aceita esses pedidos. O “stable release channel” (canal de lançamento stable) da mensagem é o Rust normal que você recebe do rustup, e ele recusa.

Repare no que o rustc não reclama: o map_windows na linha 5. Ele para antes, na linha do #![feature]. Quando você tirar essa linha, vai descobrir se o resto do código funciona no stable.

Você recebe o mesmo erro no canal beta. Se o seu código tem várias linhas #![feature], o rustc normalmente só mostra a primeira, então confira o topo do arquivo para ver se há mais.

É como um crachá de “só funcionários”. A cozinha de testes (o nightly) deixa você entrar com ele. O restaurante (o stable) não aceita esse crachá de jeito nenhum, por mais educado que você seja ao mostrá-lo.

O Rust promete que o código que compila no stable hoje vai continuar compilando em todas as próximas versões stable 1.x. Recursos inacabados não podem fazer parte dessa promessa: os nomes, os argumentos e o comportamento deles ainda podem mudar, ou eles podem ser removidos. Por isso eles vivem só no nightly, uma nova versão do compilador gerada toda noite, e você ativa cada um pelo nome com #![feature(...)].

O Rust stable não simplesmente ignora a linha: ele para com um erro. Assim você não tem como construir um projeto em cima de um recurso inacabado sem perceber. Quando um recurso fica pronto, ele passa a fazer parte do Rust stable e não precisa mais da linha.

Então, quando você vê o E0554, só existem três perguntas de verdade: existe um jeito stable de fazer isso (Correção 1), o recurso já virou stable (Correção 2), ou você quer mesmo o nightly (Correção 3)? Veja Stable, beta e nightly.

Correção 1: Remova o atributo e use a API stable

Seção intitulada “Correção 1: Remova o atributo e use a API stable”

Escolha esta quase sempre. Apague a linha #![feature] e compile de novo. Se agora aparecer o E0658 (use of unstable library feature `iter_map_windows` , uso de um recurso instável da biblioteca), o recurso ainda está inacabado, e você precisa de um jeito stable de fazer a mesma coisa. A maioria dos métodos instáveis é um atalho para algo que o Rust stable já consegue fazer. Aqui, .windows(2) num slice entrega cada par de vizinhos:

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

Saída:

[3, -2, 5]
18 -> 21
21 -> 19
19 -> 24
▶ Experimente você mesmo

Para achar o jeito stable, abra o método na documentação da biblioteca padrão. Itens instáveis têm uma caixa que diz “This is a nightly-only experimental API” (esta é uma API experimental só do nightly), e o nome do recurso na sua linha #![feature] normalmente corresponde a uma página do The Unstable Book (em inglês). Veja Slices e Iteradores.

Escolha esta quando o código é um pouco mais antigo. Muitos recursos que antes precisavam de #![feature] hoje fazem parte do Rust stable, e aí a linha simplesmente não é mais necessária. O rustc avisa isso num warning logo abaixo do erro:

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
| ^^^^^^^^^^^^^^^

O warning diz: “o recurso slice_as_chunks é stable desde a 1.88.0 e não precisa mais de um atributo para ser ativado”.

O programa com erro:

// Copied from an older tutorial
#![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);
}
}

(Os comentários querem dizer “copiado de um tutorial mais antigo” e “não é mais necessário: este recurso agora é stable”.)

Apague a linha #![feature] (e o comentário acima dela), e o resto funciona sem mudanças:

fn main() {
let pixels = [255, 0, 0, 0, 128, 255];
let (rgb, _rest) = pixels.as_chunks::<3>(); // ✅ stable desde o Rust 1.88
for [r, g, b] in rgb {
println!("r={} g={} b={}", r, g, b);
}
}

Saída:

r=255 g=0 b=0
r=0 g=128 b=255
▶ Experimente você mesmo

Para recursos da linguagem, o rustc é ainda mais direto e acrescenta help: remove the attribute (remova o atributo) embaixo do erro, mais uma linha como the feature `async_closure` has been stable since `1.85.0` and no longer requires an attribute to enable.

Não apareceu nenhum warning, mas você desconfia que o recurso já é stable? Talvez o seu Rust seja simplesmente mais antigo do que a versão em que ele ficou stable. Confira e atualize:

Terminal window
rustc --version
rustup update

Se o rustc --version continuar mostrando uma versão antiga depois disso, provavelmente o projeto tem um arquivo rust-toolchain.toml que fixa a versão. Veja Fixando uma toolchain por projeto.

Escolha esta por último, quando não existe um jeito stable e você aceita que o seu código pode quebrar com um nightly futuro. Bons motivos típicos: você está testando um recurso novo, escrevendo um pequeno experimento, ou o projeto em que você contribui já usa nightly. Instale o nightly ao lado do stable e use-o para um único comando:

Terminal window
rustup toolchain install nightly
cargo +nightly run

Ou faça o projeto inteiro usar nightly com um arquivo rust-toolchain.toml ao lado do Cargo.toml. Aí um cargo run simples escolhe o nightly nessa pasta, e o stable em todas as outras:

[toolchain]
channel = "nightly"

Num projeto que outras pessoas também compilam, fixe uma data, como channel = "nightly-2026-10-01", para que todo mundo use o mesmo compilador. No Rust Playground, escolha Nightly no menu de toolchain.

Talvez você encontre a dica de definir RUSTC_BOOTSTRAP=1 para fazer o stable aceitar #![feature]. Essa opção existe para compilar o próprio compilador do Rust. Usá-la traz todos os riscos do nightly enquanto finge que você está no stable, então não faça isso.

Benchmarks com #[bench]. Guias antigos escrevem benchmarks assim, e #![feature(test)] continua sendo só do 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
| ^^^^^^^^^^^^^^^^^
//! Price helpers.
//! Benchmark written the old way, for 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]));
}

(O comentário quer dizer “os benchmarks embutidos são só do nightly”.)

Correção: use uma crate de benchmarks que funcione no stable, como criterion ou divan, e rode cargo bench. Apagar só a linha #![feature] não basta aqui: aí o extern crate test; dá o E0658 (use of unstable library feature `test` ). Veja Desempenho.

Uma dependência que precisa do nightly. Se a linha --> aponta para uma crate dentro de ~/.cargo/registry/, em vez do seu próprio src/, é uma crate da qual você depende que usa #![feature]. Correção: leia o README da crate; muitas vezes uma versão mais nova funciona no stable (por exemplo, o framework web Rocket precisava do nightly até a 0.4, e a 0.5 roda no stable). Se não, escolha outra crate. Veja Cargo e crates.

Código copiado com #![feature(let_chains)]. As let chains (if let Some(x) = a && x > 0) ficaram stable no Rust 1.88, mas só na edição 2024. Correção: apague a linha (Correção 2) e coloque edition = "2024" no Cargo.toml. Sem isso, você recebe let chains are only allowed in Rust 2024 or later (let chains só são permitidas no Rust 2024 ou posterior).

Teste o que aprendeu

1. Você cola um código que começa com #![feature(try_blocks)] e recebe o E0554. O que isso quer dizer?

2. Embaixo do erro, o rustc avisa que o recurso é stable desde a 1.88.0. O que você deve fazer?

3. Você quer mesmo o nightly para um experimento. Qual é o jeito mais limpo?

Pontuação: 0 / 3