Erro E0658 do Rust: use of unstable library feature (recurso só do nightly)
O E0658 quer dizer: você usou algo que existe no Rust, mas ainda não está pronto, então o Rust estável não deixa você usar. Normalmente é um método que você encontrou na documentação da biblioteca padrão ou num post de blog, como .intersperse() ou .try_collect(), ou um pedaço de sintaxe como try { ... }. O seu código não está errado, e nada está quebrado no seu computador. Você só pegou um recurso que funciona apenas no compilador nightly (a versão noturna, experimental). Quase sempre existe um jeito estável de fazer a mesma coisa em uma linha. Esta página faz parte do guia de erros do compilador.
A mensagem de erro
Seção intitulada “A mensagem de erro”error[E0658]: use of unstable library feature `iter_intersperse` --> src/main.rs:3:47 |3 | let joined: String = tags.iter().copied().intersperse(", ").collect(); // ❌ nightly-only method | ^^^^^^^^^^^ | = note: see issue #79524 <https://github.com/rust-lang/rust/issues/79524> for more informationEm português: “uso de um recurso instável da biblioteca, iter_intersperse”. A nota aponta para a issue do GitHub com mais informações.
Este é o programa que gera o erro:
fn main() { let tags = ["rust", "web", "cli"]; let joined: String = tags.iter().copied().intersperse(", ").collect(); // ❌ nightly-only method println!("{}", joined);}(O comentário quer dizer “método só do nightly”. Ele fica em inglês porque aparece na saída do compilador.)
O que significa
Seção intitulada “O que significa”O ^^^^^^^^^^^ aponta para intersperse na linha 3. O título da mensagem dá o nome do recurso entre crases, iter_intersperse. Esse é o nome que o time do Rust usa para essa parte ainda não terminada da biblioteca padrão. A note: traz o link da issue do GitHub onde o recurso está sendo discutido.
Ou seja, o rustc encontrou o método. Ele sabe exatamente o que você quer. Só não vai compilar, porque intersperse ainda está marcado como instável (unstable): o nome, os argumentos ou o comportamento dele podem mudar antes de ficar pronto, ou ele pode até ser removido.
Outras formas do título querem dizer a mesma coisa, mas para recursos da linguagem em vez da biblioteca: the `!` type is experimental (o tipo ! é experimental), `try` expression is experimental (a expressão try é experimental) ou associated type defaults are unstable (valores padrão de tipos associados são instáveis).
É como uma loja com um produto novo na prateleira, com um adesivo de “só para funcionários, ainda em teste”. Você vê o produto, consegue ler a etiqueta, mas o caixa ainda não vende para você.
Por que o Rust faz isso
Seção intitulada “Por que o Rust faz isso”O Rust faz uma promessa forte: um código que compila no Rust estável hoje continua compilando em todas as versões estáveis 1.x do futuro. Para cumprir essa promessa, os recursos novos chegam primeiro no canal nightly, onde as pessoas podem experimentá-los e o design ainda pode mudar. Só quando um recurso está pronto ele vira estável, normalmente depois de meses ou anos de testes.
O Rust estável se recusa a compilar qualquer recurso instável, para você não construir em cima de algo que pode mudar debaixo dos seus pés. Se você quer mesmo experimentar um, o nightly deixa você ligá-lo pelo nome com #![feature(iter_intersperse)]. No estável, até essa linha é um erro (E0554).
A documentação da biblioteca padrão mostra os dois tipos lado a lado. Itens estáveis têm um número de versão à direita, como 1.82.0: a versão do Rust em que eles ficaram estáveis. Itens instáveis têm uma caixa que diz “🔬 This is a nightly-only experimental API.” (esta é uma API experimental, só do nightly). Essa caixa é o jeito mais rápido de identificar um E0658 antes mesmo de escrever o código. Veja Ferramentas do Rust para entender como os canais do Rust e o rustup se encaixam.
Como corrigir
Seção intitulada “Como corrigir”Correção 1: Use a alternativa estável
Seção intitulada “Correção 1: Use a alternativa estável”Escolha esta quase sempre. Métodos instáveis normalmente são atalhos para algo que o Rust estável já sabe fazer. Para juntar strings com um separador, o join de um slice ou de um Vec faz o que o intersperse(...).collect() faria:
fn main() { let tags = ["rust", "web", "cli"]; let joined = tags.join(", "); println!("{}", joined);
// Strings criadas por um iterador: junte-as num Vec primeiro e depois use join. let upper: Vec<String> = tags.iter().map(|t| t.to_uppercase()).collect(); println!("{}", upper.join(" | "));}Saída:
rust, web, cliRUST | WEB | CLISe você prefere manter tudo numa cadeia de iteradores só, o popular crate itertools tem join e intersperse estáveis para iteradores. Veja Strings e Iteradores.
Correção 2: Procure o selo “nightly-only” na documentação
Seção intitulada “Correção 2: Procure o selo “nightly-only” na documentação”Escolha esta quando você copiou um método da documentação, de uma resposta de IA ou de um post de blog. Abra o método na documentação da std: se ele tem a caixa 🔬, procure um pouco mais pelo jeito estável. Um caso comum é o .try_collect():
error[E0658]: use of unstable library feature `iterator_try_collect` --> src/main.rs:3:80 |3 | let numbers: Result<Vec<i32>, _> = inputs.iter().map(|s| s.parse::<i32>()).try_collect(); // ❌ nightly-only | ^^^^^^^^^^^ | = note: see issue #94047 <https://github.com/rust-lang/rust/issues/94047> for more informationO programa com erro:
fn main() { let inputs = ["3", "14", "x"]; let numbers: Result<Vec<i32>, _> = inputs.iter().map(|s| s.parse::<i32>()).try_collect(); // ❌ nightly-only println!("{:?}", numbers);}O Rust estável já faz isso com um collect() comum. Quando os itens são Results e você coleta num Result<Vec<_>, _>, você recebe um Ok com todos os valores, ou o primeiro Err:
use std::num::ParseIntError;
fn parse_all(inputs: &[&str]) -> Result<Vec<i32>, ParseIntError> { inputs.iter().map(|s| s.parse::<i32>()).collect()}
fn main() { println!("{:?}", parse_all(&["3", "14", "15"])); println!("{:?}", parse_all(&["3", "x", "15"]));}Saída:
Ok([3, 14, 15])Err(ParseIntError { kind: InvalidDigit })Outros instáveis que você pode encontrar, com o caminho estável: .array_chunks() num iterador (iter_array_chunks; use .as_chunks() ou .chunks() num slice) e .map_windows() (use .windows() num slice). Veja Result e Slices.
Correção 3: Atualize o Rust, se o recurso ficou estável há pouco tempo
Seção intitulada “Correção 3: Atualize o Rust, se o recurso ficou estável há pouco tempo”Escolha esta quando a documentação mostra um número de versão no lugar da caixa 🔬, ou quando o mesmo código compila para um amigo ou no Playground. Nesse caso o recurso é estável, só é mais novo que o seu compilador. Por exemplo, o as_chunks dos slices ficou estável no Rust 1.88. Num Rust mais antigo você receberia E0658 por ele; num atual, simplesmente funciona:
fn main() { let readings = [21, 22, 19, 20, 23]; let (pairs, rest) = readings.as_chunks::<2>(); for [a, b] in pairs { println!("{} e {}", a, b); } println!("sobrou: {:?}", rest);}Saída:
21 e 2219 e 20sobrou: [23]Confira a sua versão e atualize:
rustc --versionrustup updateSe depois disso o rustc --version ainda mostra uma versão antiga, procure um arquivo rust-toolchain.toml no seu projeto. Ele fixa o projeto numa versão do Rust, e o rustup show diz qual está ativa. Veja Ferramentas do Rust.
Correção 4: Ative o nightly com #![feature], só se você quiser mesmo
Seção intitulada “Correção 4: Ative o nightly com #![feature], só se você quiser mesmo”Deixe esta por último, e só quando não houver alternativa estável e você aceitar que o seu código pode quebrar num nightly futuro. Você precisa de duas coisas: uma linha #![feature(...)] no topo do main.rs (ou do lib.rs) com o nome do recurso que aparece no erro, e o compilador nightly. No estável, a própria linha #![feature] é rejeitada:
error[E0554]: `#![feature]` may not be used on the stable release channel --> src/main.rs:1:1 |1 | #![feature(iter_intersperse)] // ❌ only allowed on nightly Rust | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Em português: “#![feature] não pode ser usado no canal estável”. O programa, que só compila no nightly:
#![feature(iter_intersperse)] // ❌ only allowed on nightly Rust
fn main() { let tags = ["rust", "web", "cli"]; let joined: String = tags.iter().copied().intersperse(", ").collect(); println!("{}", joined);}(O comentário em inglês diz “só permitido no Rust nightly”.) Instale o nightly ao lado do seu Rust estável e use-o só neste projeto ou neste comando:
rustup toolchain install nightlycargo +nightly runSeja honesto consigo mesmo aqui. Para aprender, para testes e para ferramentas pequenas, o nightly serve. Para uma biblioteca da qual outras pessoas dependem, ou qualquer coisa que você precise manter, fique no estável: a maioria dos crates que você usa também fica.
Onde você costuma ver esse erro
Seção intitulada “Onde você costuma ver esse erro”Vec<i32, i32> quando você queria uma lista de pares. O segundo parâmetro do Vec é o alocador de memória, que é instável, então o primeiro erro é sobre allocator_api (e mais alguns erros vêm depois dele):
error[E0658]: use of unstable library feature `allocator_api` --> src/main.rs:2:26 |2 | let points: Vec<i32, i32> = vec![]; // ❌ meant a list of (x, y) pairs | -----^^^ | | | help: consider wrapping the inner types in tuple: `(i32, i32)`fn main() { let points: Vec<i32, i32> = vec![]; // ❌ meant a list of (x, y) pairs println!("{} points", points.len());}A ajuda sugere colocar os tipos de dentro numa tupla (o comentário em inglês diz “queria uma lista de pares (x, y)”). Correção: faça o que a ajuda diz, Vec<(i32, i32)>. Veja Vetores e Tuplas. O mesmo engano com Option ou Result é o E0107.
O tipo ! nas suas próprias assinaturas. ! quer dizer “nunca acontece”. Ele funciona como tipo de retorno de uma função que nunca retorna, mas em qualquer outro lugar ainda é instável:
error[E0658]: the `!` type is experimental --> src/main.rs:1:34 |1 | fn default_port() -> Result<u16, !> { // ❌ the `!` type is nightly-only here | ^fn default_port() -> Result<u16, !> { // ❌ the `!` type is nightly-only here Ok(8080)}
fn main() { println!("{:?}", default_port());}(O comentário em inglês diz “aqui o tipo ! é só do nightly”.) Correção: use std::convert::Infallible, o tipo estável para “este erro não pode acontecer”, ou simplesmente devolva u16 se nada pode falhar.
Blocos try. Um bloco try { ... } deixa você usar ? sem escrever uma função, mas ele é só do nightly (`try` expression is experimental). Correção: mova o código para uma função pequena que devolve Result e use ? ali, como na Correção 2. Veja Result.
Parecido, mas não é E0658: um código escrito para a edição 2024, como if let Some(a) = age && a >= 18, dá let chains are only allowed in Rust 2024 or later (let chains só são permitidas no Rust 2024 ou depois) numa edição mais antiga. Correção: coloque edition = "2024" no Cargo.toml, ou aninhe os dois ifs.
Erros relacionados
Seção intitulada “Erros relacionados”- E0554:
#![feature]may not be used on the stable release channel, o erro seguinte quando você tenta a Correção 4 no estável. - E0599: nenhum método encontrado; quando o método nem existe (ou vem de um crate que você não acrescentou), você recebe este no lugar.
- E0107: número errado de argumentos genéricos, como
Option<i32, i32>(o primo do casoVec<i32, i32>). - E0277: trait bound não satisfeito; um dos erros que vêm depois de
Vec<i32, i32>. - E0463: crate não encontrado, se você trocar para o
itertoolse esquecer de acrescentá-lo aoCargo.toml. - Todos os erros do compilador: a lista completa de páginas de erro.
Teste o que aprendeu
Seção intitulada “Teste o que aprendeu”Teste o que aprendeu
1. A página da documentação da std de um método mostra uma caixa dizendo "This is a nightly-only experimental API". O que acontece se você chamá-lo no Rust estável?
2. .try_collect() dá E0658. Qual é o jeito estável de costume para transformar um iterador de Results num Result<Vec<_>, _>?
3. Um código que compila no Playground te dá E0658 por um método cuja documentação mostra 1.88.0. O que você deve tentar primeiro?
Pontuação: 0 / 3
Para saber mais
Seção intitulada “Para saber mais”- E0658 — Rust error codes index (em inglês): a explicação oficial, e como uma linha
#![feature]ativa um recurso no nightly. - How Rust is Made and “Nightly Rust” — The Rust Book (em inglês): estável, beta e nightly, o “trem” de lançamentos e como recursos instáveis viram estáveis.
- Channels — The rustup book (em inglês): como instalar o nightly, o
cargo +nightlye como escolher uma toolchain por projeto. - The Unstable Book (em inglês): todos os nomes de recursos instáveis que podem aparecer num E0658, com uma descrição curta de cada um.
slice::join— documentação da biblioteca padrão (em inglês): o jeito estável de juntar strings com um separador, a alternativa aointersperse.