Codificação Rust
Fluxo de trabalho
-
Orientar-se. Leia as fontes de verdade do projeto antes de escrever:
rust-toolchain.toml,Cargo.toml(edition,rust-version,[lints],[workspace]),clippy.toml,rustfmt.toml,.cargo/config.toml, e a configuração de CI,justfile,Makefileouxtaskpara os comandos de verificação canônicos. Leia o módulo que você está alterando e seus vizinhos; reutilize seus helpers, tipos de erro e padrões. Concluído quando: você puder nomear a edição, a MSRV, a política de lints, cada entradadisallowed-methods/disallowed-types, e os comandos de verificação do projeto. -
Modelar os tipos. Projete dados antes do fluxo de controle, seguindo Tipos. Alterando a API pública de uma biblioteca: leia
references/api.md. Concluído quando: cada invariante da qual a alteração depende está codificada em um tipo, ou mantida por umexpectcuja mensagem nomeia a invariante. -
Implementar em loop apertado. Trabalhe em pequenos passos e execute
cargo checkapós cada um. Leia o diagnóstico completo: sua linhahelp:geralmente nomeia a correção, erustc --explain E0502expande um código de erro. Para a API de uma dependência, leia seu código-fonte na versão bloqueada (Cargo.lock) em$CARGO_HOME/registry/src/. Renomeações em massa passam por renomeação do rust-analyzer ouast-grep;cargo clippy --fixaplica sugestões automatizáveis. Correção de bug: escreva o teste de regressão primeiro e veja-o falhar. Concluído quando: a alteração compila sem avisos nas linhas que você modificou, e qualquer teste de regressão falhou antes da correção e passou depois. -
Verificar. Execute os comandos do projeto do passo 1; caso contrário:
cargo fmt --all cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test --workspace --all-features- Projeto sem política
[lints]: também executecargo clippy --all-targets -- -W clippy::pedantice corrija os acertos nas linhas que você modificou. - Features mutuamente exclusivas: substitua
--all-featurespor cada conjunto de features que o CI testa. cargo nextestpula doctests: adicionecargo test --doc.- Documentação pública alterada:
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features. unsafetocado: executereferences/unsafe.md.- Corrija lints na causa. Quando a supressão é correta, escopo
#[expect(clippy::lint_name, reason = "...")]para o menor item. Concluído quando: cada comando sai com 0, as linhas que você modificou não geram avisos, e toda nova supressão carrega umreason.
- Projeto sem política
-
Autorrevisar o diff. Releia o
git diffcompleto, não sua memória dele, contra Regras e as regras de cada arquivo de referência cujo ramo o diff toca. Concluído quando: cada trecho é exigido pela tarefa, código protótipo edbg!/todo!foram removidos, comentários de documentação correspondem ao comportamento, e toda regra aplicável se mantém para cada trecho.
Revisando código de outra pessoa: execute o passo 1, execute os comandos do passo 4 quando possível, então aplique o passo 5 ao diff deles. Reporte cada descoberta como caminho:linha, a regra e a correção.
Regras
Ownership
- Empreste em parâmetros:
&str,&[T],&Path,&T. TomeString,Vec<T>, ouTpor valor apenas quando a função armazena ou consome. - Cada
.clone()ganha seu lugar: o chamador precisa de ownership, ou o valor é um handle barato (Arc::clone(&handle)). - Quando o borrow checker reclamar, reestruture primeiro: encurte o empréstimo, empreste campos disjuntos separadamente,
std::mem::take/replace, índices para umVec. Ownership mutável compartilhado (Rc<RefCell<_>>,Arc<Mutex<_>>) é o último recurso. - Retorne
impl Iterator<Item = T>quando o chamador apenas itera.
Tipos
- Torne estados ilegais irrepresentáveis: um
enumcarregando dados por estado, no lugar de flagsboolmais camposOption; newtypes para IDs, unidades e valores validados (struct Port(NonZeroU16)). - Parse, não valide: converta entrada não confiável uma vez na fronteira (
TryFrom,FromStr,#[serde(try_from = "Raw")]) e passe o tipo parseado para dentro. - Faça match exaustivo em enums que você possui. Um braço
_só é correto quando uma variante futura deve seguir aquele ramo também. - Converta inteiros com
From/TryFrom;astrunca e inverte sinal silenciosamente.
Erros e panics
- Biblioteca: um enum
thiserrorpor domínio de falha. Binário:anyhow::Resultcom.context(...). - Panics significam bugs.
unwrap()vive em testes; código de produção usa?, ouexpect("...")declarando a invariante que torna a falha impossível.
Expressões idiomáticas atuais
Padrões mais antigos dominam os dados de treino. Prefira a forma atual quando rust-version permitir; novos crates usam edition = "2024". clippy::incompatible_msrv captura apenas APIs std mais novas; recursos de linguagem e Cargo precisam de cargo +<msrv> check.
| Prefira | Em vez de | Desde |
|---|---|---|
std::sync::LazyLock, OnceLock | lazy_static!, once_cell | 1.80, 1.70 |
let Some(x) = opt else { return ... }; | match + retorno antecipado | 1.65 |
if let Some(x) = a && x > 0 | if let aninhado | 1.88, edition 2024 |
async fn nativo em traits | #[async_trait], ainda necessário para dyn Trait | 1.75 |
| closures `async | {}, bounds AsyncFn` | |
#[expect(lint, reason = "...")] | #[allow(lint)] | 1.81 |
&raw const x, &raw mut x | ptr::addr_of! | 1.82 |
opt.is_some_and(f), opt.is_none_or(f) | map_or(false, f), map_or(true, f) | 1.70, 1.82 |
std::hint::black_box | criterion::black_box | 1.66 |
[lints] em Cargo.toml para política compartilhada | #![warn(...)] em cada raiz de crate | 1.74 |
Diretivas de build-script cargo:: | cargo: | 1.77 |
Documentação e comentários
- Itens públicos recebem documentação
///:# Errorsem funções que podem falhar,# Panicsem funções que podem entrar em pânico, exemplos como doctests usando?. - Comentários explicam o porquê; o código mostra o quê.
Dependências
- Reutilize o que o workspace já depende (
[workspace.dependencies],cargo tree -i <crate>), e prefira std quando atende à necessidade. - Adicione com
cargo add(ciente de MSRV), habilitando apenas as features que você usa.
Referências
Carregue a que corresponde ao ramo em que você está:
references/api.md: projetando ou alterando a API pública de uma biblioteca, nomeação, impls de trait, semver.references/errors.md: definindo tipos de erro, propagação, pânico versusResult.references/async.md: async, tokio, threads, canais, locks, atômicos.references/unsafe.md:unsafe, FFI, ponteiros brutos,Send/Syncmanual.references/cargo.md:Cargo.toml, workspaces, features, perfis, scripts de build, seleção de crates.references/lints.md: configurando lint para um crate ou workspace.references/testing.md: escrevendo testes, testes de propriedade e snapshot, benchmarks.references/perf.md: otimizando um caminho crítico medido.