Erro E0603 do Rust: function, struct or module is private (item privado)
O E0603 é uma boa notícia disfarçada: o Rust encontrou a função, a struct ou o módulo que você pediu. Ele só não tem permissão para entregar, porque o item é privado. Tudo num módulo Rust é privado até você dizer o contrário, então esse erro aparece para quase todo mundo na primeira vez que divide o código em módulos. A correção costuma ser uma palavra só: pub. Para os outros erros desta série, veja Erros do compilador Rust.
A mensagem de erro
Seção intitulada “A mensagem de erro”error[E0603]: function `apply_discount` is private --> src/main.rs:8:26 |8 | let total = billing::apply_discount(200); // ❌ privada | ^^^^^^^^^^^^^^ private function |note: the function `apply_discount` is defined here --> src/main.rs:2:5 |2 | fn apply_discount(price: u32) -> u32 { // sem `pub` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Em português: “a função apply_discount é privada”. A nota mostra onde a função foi definida.
Este é o programa que gera o erro:
mod billing { fn apply_discount(price: u32) -> u32 { // sem `pub` price * 90 / 100 }}
fn main() { let total = billing::apply_discount(200); // ❌ privada println!("Total: {total}");}A primeira linha diz o tipo de item, então o mesmo erro aparece em algumas variações:
| O que a primeira linha diz | O que costuma ter dado errado | Correção |
|---|---|---|
function `apply_discount` is private |
o fn não tem pub |
Correção 1 ou 2 |
struct `Order` is private |
a struct não tem pub |
Correção 1 |
module `prices` is private |
um mod no caminho não tem pub |
Correção 1 ou 3 |
function import `price_of` is private |
você chegou ao item por um use simples dentro de outro módulo |
Correção 3 |
tuple struct constructor `Percent` is private |
a struct é pub, mas os campos dela não são |
Correção 4 |
O que significa
Seção intitulada “O que significa”Leia as duas setas. A primeira (linha 8) é onde você usa o item. A seta do note: (linha 2) é onde o item é definido. O Rust está dizendo: “estou vendo apply_discount ali, mas ela nunca foi marcada como compartilhada, então o código fora de billing não pode chamá-la”.
O arquivo não importa. Se billing estiver em src/billing.rs, você recebe o mesmo erro, e o note: simplesmente aponta para src/billing.rs:1:1.
Pense num prédio de escritórios. Cada módulo é uma sala com porta. Um item privado é uma ferramenta que fica na sala dela: quem está dentro da sala (e nas salas menores dentro dela) pode usar, mas ninguém do corredor pode. O pub coloca a ferramenta numa prateleira no corredor.
Por que o Rust faz isso
Seção intitulada “Por que o Rust faz isso”O Rust deixa tudo privado por padrão: funções, structs, campos de structs, módulos e até imports com use. Você escolhe compartilhar com pub. A lição de Módulos mostra isso desde o começo.
O motivo é a segurança do você do futuro. Tudo o que é pub vira uma promessa: outro código pode depender daquilo, então mudar pode quebrar esse código. Itens privados podem ser alterados, renomeados ou apagados à vontade, e o compilador garante que ninguém de fora depende deles. Funções auxiliares continuam auxiliares, e uma struct pode proteger as próprias regras (como “o saldo nunca é negativo”), porque ninguém mais mexe nos campos dela diretamente.
Mais um detalhe: a privacidade é verificada em cada passo de um caminho. shop::prices::price_of só funciona se prices estiver visível para você e price_of também. Um pub fn dentro de um módulo privado continua fora de alcance.
Como corrigir
Seção intitulada “Como corrigir”Correção 1: Coloque pub no item (e em cada módulo do caminho)
Seção intitulada “Correção 1: Coloque pub no item (e em cada módulo do caminho)”Escolha esta quando o item foi feito para ser usado de fora do módulo. Na maioria das vezes, é a correção certa:
mod billing { pub fn apply_discount(price: u32) -> u32 { price * 90 / 100 }}
fn main() { let total = billing::apply_discount(200); println!("Total: {total}");}Saída:
Total: 180Se o erro disser module `prices` is private (o módulo prices é privado), o pub que falta está no módulo: escreva pub mod prices { ... }. O rustc também indica esse caso com um segundo rótulo, function `price_of` is not publicly re-exported (a função price_of não é reexportada publicamente). Com um arquivo separado, o pub vai na linha da declaração: pub mod prices;.
Numa struct, pub struct Order torna o tipo público, mas cada campo ainda precisa do próprio pub se o código de fora tiver que ler ou alterar esse campo. Mais sobre isso na Correção 4.
Correção 2: Use pub(crate) ou pub(super) para “só o meu código”
Seção intitulada “Correção 2: Use pub(crate) ou pub(super) para “só o meu código””Escolha esta quando o item deve ser compartilhado, mas não com o mundo inteiro. O pub tem alguns níveis, do menor para o maior:
| Você escreve | Quem pode usar o item |
|---|---|
| nada (privado) | o próprio módulo e os módulos dentro dele |
pub(super) |
também o módulo pai |
pub(crate) |
qualquer código deste crate |
pub |
todo mundo, incluindo outros crates que dependem do seu |
Num programa (um binário), pub(crate) e pub se comportam quase igual. A diferença importa numa biblioteca: pub(crate) deixa os seus módulos compartilharem uma função auxiliar sem que ela vire parte da API pública da biblioteca.
mod shop { // Qualquer código deste crate pode chamar esta função. pub(crate) fn store_name() -> &'static str { "Ferris Fruits" }
pub mod receipt { // Só o módulo pai, `shop`, pode chamar esta função auxiliar. pub(super) fn line(item: &str, price: u32) -> String { format!("{item}: {price}") } }
pub fn print_receipt(items: &[(&str, u32)]) { println!("== {} ==", store_name()); for (item, price) in items { println!("{}", receipt::line(item, *price)); } }}
fn main() { println!("Boas-vindas à {}", shop::store_name()); shop::print_receipt(&[("apple", 3), ("pear", 5)]); // shop::receipt::line("apple", 3); // ❌ E0603: `line` é só para `shop`}Saída:
Boas-vindas à Ferris Fruits== Ferris Fruits ==apple: 3pear: 5Tire o // da frente da última linha e você recebe function `line` is private (a função line é privada), mesmo com o pub(super). main não é o pai de receipt, então a porta continua fechada.
Correção 3: Reexporte com pub use
Seção intitulada “Correção 3: Reexporte com pub use”Escolha esta quando o módulo interno é um detalhe de implementação, mas um item dentro dele deve ser fácil de alcançar. Mantenha o módulo privado e coloque o item num caminho público mais curto:
mod shop { mod prices { // continua privado: como os preços são guardados é assunto do shop pub fn price_of(item: &str) -> u32 { if item == "apple" { 3 } else { 5 } } }
pub use prices::price_of; // agora dá para chegar como shop::price_of}
fn main() { println!("Maçãs custam {}", shop::price_of("apple")); println!("Peras custam {}", shop::price_of("pear"));}Saída:
Maçãs custam 3Peras custam 5Esta também é a correção para function import `price_of` is private (o import da função price_of é privado). Um use prices::price_of; simples dentro de shop é um atalho só para o shop; como todo o resto, um use é privado. O pub use transforma o atalho numa porta pública. Crates grandes fazem isso o tempo todo, e é por isso que você pode escrever serde::Serialize sem saber em qual módulo interno ele mora.
Correção 4: Crie um pub fn new em vez de tornar os campos públicos
Seção intitulada “Correção 4: Crie um pub fn new em vez de tornar os campos públicos”Escolha esta quando o erro é sobre os campos de uma struct ou sobre o construtor dela. Aqui a struct é pub, mas o campo não é:
mod billing { pub struct Percent(u8);}
fn main() { let discount = billing::Percent(150); // ❌ construtor privado}error[E0603]: tuple struct constructor `Percent` is private --> src/main.rs:6:29 |2 | pub struct Percent(u8); | -- a constructor is private if any of the fields is private...6 | let discount = billing::Percent(150); // ❌ construtor privado | ^^^^^^^ private tuple struct constructor |help: consider making the field publicly accessible |2 | pub struct Percent(pub u8); | +++O compilador explica que um construtor é privado se qualquer um dos campos for privado e sugere tornar o campo público. O rustc propõe pub u8, e para um tipo que só guarda dados isso não tem problema. Mas olhe o valor: 150 por cento! Muitas vezes o campo privado é justamente o objetivo. O módulo quer verificar o valor antes de um Percent existir. Dê a ele um construtor público que faz essa verificação:
mod billing { pub struct Percent(u8);
impl Percent { pub fn new(value: u8) -> Option<Percent> { if value <= 100 { Some(Percent(value)) } else { None } }
pub fn apply(&self, price: u32) -> u32 { price * (100 - self.0 as u32) / 100 } }}
fn main() { let ten = billing::Percent::new(10).unwrap(); println!("200 com 10% de desconto: {}", ten.apply(200)); println!("150% é permitido? {}", billing::Percent::new(150).is_some());}Saída:
200 com 10% de desconto: 180150% é permitido? falseAgora todo Percent do programa inteiro está garantidamente entre 0 e 100, e apply nunca dá underflow (resultado abaixo de zero). Lembre que o próprio new também precisa de pub; um método privado gera outro erro, o E0624 (associated function `new` is private). Veja Structs para saber mais sobre construtores.
Onde você costuma ver esse erro
Seção intitulada “Onde você costuma ver esse erro”Um pacote com main.rs e lib.rs. São dois crates separados, e o main.rs usa a biblioteca de fora. Se lib.rs diz mod inventory;, então use shop::inventory::count_items; no main.rs falha:
error[E0603]: module `inventory` is private --> src/main.rs:1:11 |1 | use shop::inventory::count_items; | ^^^^^^^^^ private moduleO compilador avisa que o módulo inventory é privado. Correção: escreva pub mod inventory; no lib.rs e pub fn count_items no módulo. Cuidado: pub(crate) não basta aqui. Para a biblioteca, o main.rs é outro crate, então um pub(crate) fn continua dando function `count_items` is private. Veja Cargo e crates.
Campos privados de structs. Eles têm códigos de erro próprios. Criar uma struct com um campo privado dá E0451, e ler esse campo dá E0616:
error[E0451]: field `balance` of struct `Account` is privateerror[E0616]: field `balance` of struct `Account` is privateNos dois casos, o campo balance da struct Account é privado. Correção: a mesma escolha da Correção 4. Coloque pub no campo se qualquer um pode alterá-lo, ou mantenha-o privado e acrescente pub fn new(...) mais um getter como pub fn balance(&self) -> u64.
Uma função que você achou no código-fonte de um crate. Você leu um crate no GitHub, achou a função auxiliar perfeita e recebe o E0603 ao chamá-la. Se os autores do crate não a fizeram pub, você não pode usá-la, e eles podem mudá-la a qualquer momento. Procure uma forma pública de fazer a mesma coisa na página do crate no docs.rs; só itens pub aparecem lá.
Erros relacionados
Seção intitulada “Erros relacionados”- E0432:
unresolved import(import não resolvido). O item nem foi encontrado. No E0603 ele foi encontrado, mas é privado. - E0433:
failed to resolve(falha ao resolver), um caminho no seu código que não leva a lugar nenhum. - E0451 e E0616: um campo de struct é privado (ao criar a struct ou ao ler o campo).
- E0624: um método ou uma função associada (como
new) é privado. - 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. mod shop { mod prices { pub fn price_of() {} } } e main chama shop::prices::price_of(). Qual erro aparece?
2. Uma função auxiliar em src/lib.rs está marcada como pub(crate). O src/main.rs do mesmo pacote pode chamá-la?
3. Uma pub struct Email(String); mantém o campo privado de propósito. Qual é o jeito amigável de deixar outros módulos criarem uma?
Pontuação: 0 / 3
Para saber mais
Seção intitulada “Para saber mais”- E0603 — Rust error codes index (em inglês): a explicação oficial, com um exemplo mínimo.
- Paths for Referring to an Item in the Module Tree — The Rust Book (em inglês): como expor caminhos com
pube como opubfunciona em structs e enums. - Bringing Paths into Scope with the
useKeyword — The Rust Book (em inglês): como reexportar nomes compub use. - Visibility — Rust by Example (em inglês):
pub,pub(crate),pub(super)epub(in path)num único exemplo para rodar. - Visibility and privacy — The Rust Reference (em inglês): as regras exatas, para quando você quiser o quadro completo.