Erro E0624 do Rust: method is private (método privado)
O E0624 quer dizer: o método que você chamou existe, mas foi escrito sem pub, então só o código dentro do módulo dele pode chamá-lo. A struct pode ser pública, e o módulo também. Mesmo assim, os métodos começam privados, um por um. É muito comum logo depois de mover um tipo para um módulo próprio, e a correção costuma ser colocar pub antes do fn. Para os outros erros desta série, veja Erros do compilador Rust.
A mensagem de erro
Seção intitulada “A mensagem de erro”error[E0624]: associated function `new` is private --> src/main.rs:18:38 | 7 | fn new() -> Account { // sem `pub` | ------------------- private associated function defined here...18 | let mut account = bank::Account::new(); // ❌ função associada privada | ^^^ private associated function
error[E0624]: method `add_interest` is private --> src/main.rs:19:13 |11 | fn add_interest(&mut self) { // sem `pub` | -------------------------- private method defined here...19 | account.add_interest(); // ❌ método privado | ^^^^^^^^^^^^ private methodEm português: “a função associada new é privada” e “o método add_interest é privado”. Cada erro mostra onde a função privada foi definida (defined here) e onde você tentou chamá-la.
Este é o programa que gera o erro:
mod bank { pub struct Account { balance: u64, }
impl Account { fn new() -> Account { // sem `pub` Account { balance: 0 } }
fn add_interest(&mut self) { // sem `pub` self.balance += self.balance / 100; } }}
fn main() { let mut account = bank::Account::new(); // ❌ função associada privada account.add_interest(); // ❌ método privado}O rustc usa dois nomes aqui. Um método recebe self (account.add_interest()). Uma função associada não tem self e é chamada com :: (Account::new()). A regra e a correção são as mesmas para os dois.
O que significa
Seção intitulada “O que significa”Cada erro tem duas setas. A seta ^^^ é a sua chamada. A seta --- mostra a linha do fn que está sem pub. Ou seja, a mensagem diz exatamente onde colocá-lo.
Estar dentro de impl Account não torna um método público, mesmo quando Account é pub. Pense num restaurante: o cardápio é público, então você pode pedir os pratos (os métodos pub). A cozinha tem as próprias etapas, como “picar a cebola”, que você não pode pedir diretamente. Essas etapas são os métodos privados.
Por que o Rust faz isso
Seção intitulada “Por que o Rust faz isso”Tudo em Rust é privado por padrão, e os métodos não são exceção (veja Módulos). A privacidade pertence ao módulo onde o bloco impl foi escrito: qualquer código em mod bank pode chamar add_interest, e o código de fora não pode.
Isso deixa um tipo ter pequenos métodos auxiliares que só fazem sentido na ordem certa. Imagine que add_interest deve rodar uma vez por mês, depois de cobrar as tarifas. Se qualquer um pudesse chamá-lo, alguém acabaria chamando duas vezes sem querer. Auxiliares privados, mais um método público que os roda do jeito certo, tornam esse erro impossível.
Também deixa as suas opções em aberto. Métodos privados podem ser renomeados, juntados ou apagados a qualquer momento, porque o compilador garante que nenhum código de fora usa esses métodos.
Como corrigir
Seção intitulada “Como corrigir”Correção 1: Coloque pub no método
Seção intitulada “Correção 1: Coloque pub no método”Escolha esta quando o método foi feito para ser chamado de fora. Para o new isso quase sempre é verdade: um construtor que ninguém pode chamar não serve para muita coisa.
mod bank { pub struct Account { balance: u64, }
impl Account { pub fn new(opening: u64) -> Account { Account { balance: opening } }
pub fn add_interest(&mut self) { self.balance += self.balance / 100; // 1% }
pub fn balance(&self) -> u64 { self.balance } }}
fn main() { let mut account = bank::Account::new(1000); account.add_interest(); println!("Saldo: {}", account.balance());}Saída:
Saldo: 1010Correção 2: Chame o método público feito para você
Seção intitulada “Correção 2: Chame o método público feito para você”Escolha esta quando o método privado é um auxiliar, principalmente em código que você não escreveu. Muitas vezes existe um método público que o chama por você, na ordem certa e com as verificações certas. Aqui, manter add_interest privado é o design correto:
mod bank { pub struct Account { balance: u64, }
impl Account { pub fn new(opening: u64) -> Account { Account { balance: opening } }
// A porta de entrada pública: uma chamada faz o mês inteiro, na ordem certa. pub fn close_month(&mut self) { self.charge_fee(); self.add_interest(); }
pub fn balance(&self) -> u64 { self.balance }
// Auxiliares privados: chamá-los sozinhos, ou duas vezes, dá resultado errado. fn charge_fee(&mut self) { self.balance = self.balance.saturating_sub(5); }
fn add_interest(&mut self) { self.balance += self.balance / 100; } }}
fn main() { let mut account = bank::Account::new(1000); account.close_month(); println!("Depois de um mês: {}", account.balance()); // account.add_interest(); // ❌ E0624: method `add_interest` is private}Saída:
Depois de um mês: 1004Uma boa regra: só deixe um método pub se chamá-lo sozinho, a qualquer momento, não tiver como quebrar a struct. Se ele só faz sentido como uma etapa de algo maior, mantenha-o privado e exponha a coisa maior.
Correção 3: Use pub(crate) para “só o meu código”
Seção intitulada “Correção 3: Use pub(crate) para “só o meu código””Escolha esta quando outros módulos do seu crate precisam do método, mas quem usa a sua biblioteca não deveria. pub(super) (só o módulo pai) funciona do mesmo jeito; a página do E0603 tem uma tabela com todos os níveis.
mod shop { pub struct Cart { prices: Vec<u32>, }
impl Cart { pub fn new() -> Cart { Cart { prices: Vec::new() } }
pub fn add(&mut self, price: u32) { self.prices.push(price); }
// Só para o nosso próprio código (como os recibos), não para quem usa a biblioteca. pub(crate) fn total(&self) -> u32 { self.prices.iter().sum() } }}
mod receipt { pub fn print(cart: &crate::shop::Cart) { println!("Total: {}", cart.total()); }}
fn main() { let mut cart = shop::Cart::new(); cart.add(3); cart.add(5); receipt::print(&cart);}Saída:
Total: 8Um porém: num pacote com src/lib.rs e src/main.rs, eles são dois crates. Um pub(crate) fn total em lib.rs é privado para main.rs:
error[E0624]: method `total` is private --> src/main.rs:3:25 | 3 | println!("{}", cart.total()); | ^^^^^ private method | ::: src/lib.rs:10:5 |10 | pub(crate) fn total(&self) -> u32 { | --------------------------------- private method defined hereO rustc mostra a chamada em src/main.rs e a definição em src/lib.rs. Nesse caso, use pub simples. Veja Cargo e crates.
Correção 4: Leve o código que precisa dele para dentro do módulo
Seção intitulada “Correção 4: Leve o código que precisa dele para dentro do módulo”Escolha esta quando o método realmente deve continuar privado, mas algum código precisa dele mesmo assim, como uma auditoria ou um teste. O código do mesmo módulo pode chamá-lo, e um módulo filho também: módulos dentro de bank enxergam tudo o que é privado em bank.
mod bank { pub struct Account { balance: u64, }
impl Account { pub fn new(opening: u64) -> Account { Account { balance: opening } }
fn is_suspicious(&self) -> bool { self.balance > 10_000 } }
// Um módulo filho pode usar tudo o que é privado no módulo pai. pub mod audit { pub fn check(account: &super::Account) -> &'static str { if account.is_suspicious() { "precisa de revisão" } else { "ok" } } }}
fn main() { let small = bank::Account::new(500); let big = bank::Account::new(50_000); println!("pequena: {}", bank::audit::check(&small)); println!("grande: {}", bank::audit::check(&big));}Saída:
pequena: okgrande: precisa de revisãoOs testes de unidade funcionam do mesmo jeito. Um mod tests escrito dentro de bank (ou no fim de src/bank.rs) é um módulo filho, então pode chamar métodos privados. Veja Testes:
#[cfg(test)]mod tests { use super::*;
#[test] fn not_suspicious_when_small() { let account = Account::new(500); assert!(!account.is_suspicious()); // privado, mas permitido aqui }}Onde você costuma ver esse erro
Seção intitulada “Onde você costuma ver esse erro”Um bloco impl em outro módulo. A privacidade pertence ao módulo onde o impl foi escrito, não à struct. Se Order mora em mod model, mas você escreve impl Order { fn with_tax(&self) ... } dentro de mod pricing, o main recebe method `with_tax` is private, apontando para mod pricing. Correção: pub fn with_tax, ou pub(crate).
Usar um método como valor de função. accounts.iter().map(bank::Account::audit) é a mesma chamada escrita de outro jeito, então dá o mesmo E0624. A correção é a mesma.
Métodos de trait. Você nunca escreve pub em métodos dentro de impl SomeTrait for Type. Eles são tão públicos quanto o trait, e colocar pub é um erro: error[E0449]: visibility qualifiers are not permitted here (qualificadores de visibilidade não são permitidos aqui). Se um método de trait parece estar faltando, você recebe o E0599, e a correção é trazer o trait com use.
Um método privado de um crate. Você achou o método perfeito no código-fonte de um crate no GitHub, mas ele não é pub. Você não pode chamá-lo, e os autores podem mudá-lo em qualquer versão. Procure um método público que faça o serviço na página do crate no docs.rs; só itens pub aparecem lá.
Erros relacionados
Seção intitulada “Erros relacionados”- E0603:
function `x` is private. A mesma ideia para funções soltas, structs e módulos. - E0616:
field `x` of struct `Y` is private, ao ler ou alterar um campo. - E0451: um campo privado ao montar uma struct com
Y { ... }. Costuma se resolver com umpub fn new. - E0599:
no method named `x` found. O método não existe para esse tipo, ou o trait dele não está no escopo. - 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. pub struct Timer tem impl Timer { fn start() -> Timer { ... } } dentro de mod clock. O que acontece quando o main chama clock::Timer::start()?
2. Que código pode chamar um método privado definido em mod bank?
3. Um add_interest privado só pode rodar uma vez por mês, depois das tarifas. Qual é a melhor correção para o E0624?
Pontuação: 0 / 3
Para saber mais
Seção intitulada “Para saber mais”- E0624 — Rust error codes index (em inglês): a explicação oficial, com um exemplo mínimo.
- Method Syntax — The Rust Book (em inglês): métodos, funções associadas e blocos
impl. - Paths for Referring to an Item in the Module Tree — The Rust Book (em inglês): como expor itens com
pub, passo a passo. - Testing Private Functions — The Rust Book (em inglês): por que os testes de unidade podem chamar código privado.
- Visibility and privacy — The Rust Reference (em inglês): as regras exatas, incluindo
pub(crate),pub(super)epub(in path).