Erros do compilador Rust explicados
Apareceu um erro vermelho do compilador Rust e você não sabe bem o que ele quer? Você está no lugar certo. Todo mundo que programa em Rust vê esses erros, muitas vezes por dia. A boa notícia: são poucos os que aparecem de novo e de novo e, depois que você os conhece, eles deixam de assustar.
Cada página abaixo trata de um código de erro: mostra a mensagem real, explica em palavras simples e traz correções que você pode rodar no navegador.
Os erros mais comuns
Seção intitulada “Os erros mais comuns”| Erro | O que o compilador diz | Em palavras simples |
|---|---|---|
| E0382 | borrow of moved value | Você entregou um valor e depois tentou usá-lo de novo |
| E0502 | cannot borrow as mutable because it is also borrowed as immutable | Você está alterando algo enquanto alguém ainda está lendo |
| E0499 | cannot borrow as mutable more than once at a time | Dois lugares querem alterar a mesma coisa ao mesmo tempo |
| E0308 | mismatched types | Você passou um tipo onde se esperava outro |
| E0277 | the trait bound is not satisfied | Um tipo não sabe fazer algo que você pediu (imprimir, comparar, somar…) |
| E0106 | missing lifetime specifier | O Rust não consegue saber por quanto tempo uma referência retornada continua válida |
| E0425 | cannot find value in this scope | Um nome está escrito errado ou é usado fora do bloco onde existe |
| E0599 | no method named … found | O método não existe nesse tipo, ou o trait dele não foi importado |
| E0384 | cannot assign twice to immutable variable | Você alterou uma variável que não foi declarada com mut |
| E0596 | cannot borrow as mutable, as it is not declared as mutable | Você tentou alterar algo por meio de uma variável ou referência que não é mut |
| E0597 | borrowed value does not live long enough | Uma referência ainda está em uso depois que o valor para o qual ela aponta já sumiu |
| E0515 | cannot return reference to local variable | Você retornou uma referência para algo que é descartado quando a função termina |
| E0373 | closure may outlive the current function, but it borrows … | Uma closure (muitas vezes uma thread) pega emprestada uma variável local que pode sumir antes de ela rodar |
| E0369 | binary operation == cannot be applied to type … |
Seu tipo (ainda) não aceita ==, <, + e companhia |
| E0432 | unresolved import | Uma linha use aponta para um crate, módulo ou item que não foi encontrado |
| E0433 | cannot find type … in this scope (older: failed to resolve) | Um caminho como HashMap::new() usa um nome que não foi importado ou não existe |
| E0424 | self value is a keyword only available in methods with a self parameter |
Você usou self numa função que não recebe self |
| E0061 | this function takes N arguments but M arguments were supplied | Você passou argumentos demais ou de menos (o Rust não tem argumentos opcionais) |
| E0594 | cannot assign to p.hp, as p is not declared as mutable |
Você alterou um campo ou um valor atrás de & sem acesso mut |
| E0004 | non-exhaustive patterns: X not covered |
Seu match não trata todos os valores possíveis |
| E0507 | cannot move out of x which is behind a shared reference |
Você tentou tomar posse de algo que só tinha pegado emprestado |
| E0603 | function x is private |
Você usou uma função, struct ou módulo que não é pub |
| E0716 | temporary value dropped while borrowed | Você guardou uma referência para um valor que é jogado fora no fim da linha |
| E0463 | can’t find crate for x |
Um crate (ou a biblioteca padrão de um target) não está instalado |
| E0368 | binary assignment operation += cannot be applied to type … |
Seu tipo não aceita +=, -= e companhia |
| E0057 | this function takes N arguments but M were supplied (note: closure defined here) | Você chamou uma closure com argumentos demais ou de menos |
| E0282 | type annotations needed | O Rust não consegue descobrir um tipo sozinho, então você precisa dizer qual é |
| E0609 | no field x on type T |
O nome do campo está errado, ou o valor está embrulhado (por exemplo, num Option) |
| E0593 | closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments | Uma closure recebe argumentos separados onde se espera uma tupla (ou outra quantidade) |
| E0631 | type mismatch in closure arguments | O tipo do parâmetro de uma closure não combina com o que ela recebe (muitas vezes i32 contra &i32) |
| E0005 | refutable pattern in local binding | let Some(x) = … pode falhar, então um let simples não aceita |
| E0615 | attempted to take value of method len on type String |
Você escreveu s.len em vez de s.len() |
| E0610 | {integer} is a primitive type and therefore doesn’t have fields |
Você usou .campo num número, bool ou char |
| E0560 | struct User has no field named nmae |
Ao criar uma struct, você usou um nome de campo que ela não tem |
| E0616 | field balance of struct Account is private |
Você leu, de fora do módulo, um campo que não é pub |
| E0451 | field x of struct Y is private |
Você criou uma struct com a sintaxe literal, mas alguns campos dela são privados |
| E0624 | method x is private |
Você chamou um método ou uma função associada que não é pub |
| E0283 | type annotations needed (cannot infer type … multiple impls satisfy this bound) | Vários tipos serviriam (por exemplo, em .collect() ou .sum()), então você precisa escolher um |
| E0284 | type annotations needed: cannot satisfy <_ as FromStr>::Err == _ |
"42".parse() não sabe para qual tipo converter |
| E0790 | cannot call associated function on trait without specifying the corresponding impl type |
Você escreveu Default::default() ou Trait::new() sem dizer qual é o tipo |
| E0559 | variant Shape::Circle has no field named r |
Ao criar uma variante de enum, você usou um nome de campo que ela não tem |
| E0063 | missing field email in initializer of User |
Você criou uma struct, mas deixou um ou mais campos de fora |
| E0689 | can’t call method pow on ambiguous numeric type {integer} |
2.pow(10) ou 2.0.sqrt() precisa de um tipo numérico concreto, como i32 ou f64 |
| E0034 | multiple applicable items in scope | Dois traits dão ao seu tipo um método com o mesmo nome, e o Rust não consegue escolher um |
| E0412 | cannot find type X in this scope (Rust 1.93+ prints E0425) |
O nome de um tipo está escrito errado, não foi importado ou não foi declarado |
| E0428 | the name area is defined multiple times |
Dois itens têm o mesmo nome; o Rust não tem sobrecarga de funções |
| E0026 | variant Shape::Circle does not have a field named r |
Um pattern cita um campo que a struct ou a variante não tem |
| E0027 | pattern does not mention fields id, paid |
Um pattern de struct deixa campos de fora; acrescente-os ou termine com .. |
| E0533 | expected unit struct, unit variant or constant, found struct variant Shape::Circle |
Uma variante com campos (ou uma função) foi usada onde se espera um nome simples; acrescente { .. } |
| E0592 | duplicate definitions with name reset |
Dois blocos impl definem um método com o mesmo nome |
| E0255 | the name Error is defined multiple times |
Um import com use tem o mesmo nome de um tipo ou função seu |
| E0252 | the name Result is defined multiple times |
Duas linhas use trazem o mesmo nome; renomeie uma com as |
| E0411 | cannot find type Self in this scope |
Você usou Self fora de um impl ou de um trait |
| E0405 | cannot find trait Display in this scope |
O nome de um trait está escrito errado ou não foi importado (por exemplo, use std::fmt::Display;) |
| E0532 | expected unit struct, unit variant or constant, found tuple variant Shape::Circle |
Um pattern cita uma variante de tupla (ou uma struct) sem os ( ), ou põe ( ) onde não cabem |
| E0164 | expected tuple struct or tuple variant, found struct variant Shape::Circle |
Um pattern usa ( ) numa variante de struct ou num item associado; use { } ou um guard |
| E0404 | expected trait, found derive macro Debug |
Você escreveu impl X for ou T: X, mas X é uma struct, um alias ou uma macro derive sem o trait importado |
| E0401 | can’t use generic parameters from outer item | Uma fn interna usa o T ou o Self da função de fora; dê a ela os seus próprios genéricos ou use uma closure |
| E0107 | enum takes 2 generic arguments but 1 generic argument was supplied | Result<u32>, HashMap<String> e afins: argumentos < > de menos ou demais |
| E0530 | match bindings cannot shadow tuple variants | Um nome de variante sozinho, como Circle => (depois de use Shape::*), não pode ser uma variável nova |
| E0434 | can’t capture dynamic environment in a fn item | Uma fn interna não enxerga as variáveis locais de fora; use uma closure ou passe os valores como argumento |
| E0601 | main function not found in crate main |
O binário não tem fn main() (falta, está escrita errado, está dentro de um mod ou o código é, na verdade, uma biblioteca) |
| E0658 | use of unstable library feature iter_intersperse |
Você usou uma API só do nightly no Rust estável; use a alternativa estável ou atualize o Rust |
| E0614 | type u32 cannot be dereferenced |
Você escreveu *x, mas x já é um valor comum, e não uma referência |
| E0435 | attempt to use a non-constant value in a constant | Um const, o tamanho de um array ou um static usa uma variável let; transforme-a num const ou use um Vec |
| E0554 | #![feature] may not be used on the stable release channel |
Código copiado que só roda no nightly; remova o atributo e use a API stable, ou use o nightly de propósito |
Como ler um erro do Rust
Seção intitulada “Como ler um erro do Rust”As mensagens de erro do Rust são famosas por ajudar muito, mas trazem bastante informação de uma vez. Veja uma de verdade:
fn main() { let name = String::from("Ferris"); let greeting = name; println!("{name}");}error[E0382]: borrow of moved value: `name` --> src/main.rs:4:16 |2 | let name = String::from("Ferris"); | ---- move occurs because `name` has type `String`, which does not implement the `Copy` trait3 | let greeting = name; | ---- value moved here4 | println!("{name}"); | ^^^^ value borrowed here after move |help: consider cloning the value if the performance cost is acceptable |3 | let greeting = name.clone(); | ++++++++Leia nesta ordem:
- A primeira linha é o resumo: o código do erro (
E0382) e uma descrição de uma linha (aqui, “borrow of moved value” quer dizer “empréstimo de um valor que já foi movido”). - A linha da seta (
--> src/main.rs:4:16) mostra o arquivo, a linha e a coluna onde deu problema. - As marcas
^^^^apontam o lugar exato do erro. As marcas----contam a história até ali. Aqui elas dizem: o valor foi criado na linha 2, movido na linha 3 e depois usado na linha 4. help:é a correção que o compilador sugere, muitas vezes com o código exato a acrescentar (as marcas++++mostram os caracteres novos). Nem sempre é a melhor correção, mas é um ótimo ponto de partida.
Comece pelo primeiro erro. Um único engano pode causar uma cadeia de erros seguintes, e corrigir o primeiro muitas vezes faz o resto sumir.
Três hábitos que ajudam
Seção intitulada “Três hábitos que ajudam”-
Peça mais detalhes ao compilador. Todo código de erro vem com uma explicação mais longa embutida. Rode isto num terminal:
Terminal window rustc --explain E0382Você recebe uma descrição curta, um exemplo com o erro e um exemplo corrigido (em inglês).
-
Verifique com frequência. O
cargo checkencontra erros sem compilar o programa inteiro, então é bem mais rápido que ocargo build. Rodando ele a cada poucas linhas, você encontra um erro por vez, e não vinte. Veja Cargo e crates. -
Deixe o editor mostrar os erros enquanto você digita. Com a extensão rust-analyzer, os erros aparecem direto no seu código, com o mesmo texto de ajuda. Veja Ferramentas do Rust.
Por que o Rust tem tantos erros
Seção intitulada “Por que o Rust tem tantos erros”A maioria desses erros existe porque o Rust verifica, antes de o programa rodar, coisas que outras linguagens só descobrem em tempo de execução (ou nunca): usar memória já liberada, duas threads alterando os mesmos dados, uma verificação de null esquecida. Cada erro que você corrige é um bug que nunca vai chegar aos seus usuários.
Por isso muita gente diz: em Rust, a briga acontece na hora de compilar e, depois, o programa simplesmente funciona. As regras por trás dos erros mais comuns estão explicadas em Ownership, Borrowing e Lifetimes.
Teste o que aprendeu
Seção intitulada “Teste o que aprendeu”Teste o que aprendeu
1. Um erro do Rust mostra vários problemas. Qual você deve corrigir primeiro?
2. O que faz o comando rustc --explain E0382?
3. Numa mensagem de erro, o que as marcas ^^^^ mostram?
Pontuação: 0 / 3
Para saber mais
Seção intitulada “Para saber mais”- Rust Compiler Error Index (em inglês): a lista oficial de todos os códigos de erro, cada um com um exemplo com erro e outro corrigido.
- Understanding Ownership — The Rust Book (em inglês): as regras por trás dos erros mais comuns de borrowing e de move.
- Error Handling — The Rust Book (em inglês): como o Rust trata erros nos seus próprios programas (
Resultepanic!), e não só erros do compilador. - What is rustc? — The rustc Book (em inglês): como o compilador funciona, incluindo as opções de linha de comando e os níveis de lint.