Erreur Rust E0624 : method is private (méthode privée)
E0624 veut dire : la méthode que vous appelez existe, mais elle a été écrite sans pub, donc seul le code à l’intérieur de son module peut l’appeler. La struct peut être publique, le module aussi : les méthodes, elles, commencent quand même privées, une par une. C’est très courant juste après avoir déplacé un type dans son propre module, et la correction consiste généralement à ajouter pub devant fn. Cette page fait partie du guide des erreurs du compilateur Rust.
Le message d’erreur
Section intitulée « Le message d’erreur »error[E0624]: associated function `new` is private --> src/main.rs:18:38 | 7 | fn new() -> Account { // no `pub` | ------------------- private associated function defined here...18 | let mut account = bank::Account::new(); // ❌ private associated function | ^^^ private associated function
error[E0624]: method `add_interest` is private --> src/main.rs:19:13 |11 | fn add_interest(&mut self) { // no `pub` | -------------------------- private method defined here...19 | account.add_interest(); // ❌ private method | ^^^^^^^^^^^^ private methodLe compilateur vous dit : « la fonction associée new est privée » et « la méthode add_interest est privée ». Les étiquettes defined here montrent où chacune est définie.
Voici le programme qui la provoque :
mod bank { pub struct Account { balance: u64, }
impl Account { fn new() -> Account { // no `pub` Account { balance: 0 } }
fn add_interest(&mut self) { // no `pub` self.balance += self.balance / 100; } }}
fn main() { let mut account = bank::Account::new(); // ❌ private associated function account.add_interest(); // ❌ private method}(Les commentaires disent : pas de pub sur les deux fn, et les deux appels de main visent une fonction privée.)
Rustc utilise ici deux noms. Une méthode prend self (account.add_interest()). Une fonction associée n’a pas de self et s’appelle avec :: (Account::new()). La règle et la correction sont les mêmes pour les deux.
Ce que ça veut dire
Section intitulée « Ce que ça veut dire »Chaque erreur a deux flèches. La flèche ^^^ montre votre appel. La flèche --- montre la ligne fn à laquelle il manque pub. Le message vous dit donc exactement où l’ajouter.
Être dans impl Account ne rend pas une méthode publique, même quand Account est pub. Pensez à un restaurant : la carte est publique, vous pouvez donc commander des plats (les méthodes pub). La cuisine a ses propres étapes, comme « émincer les oignons », que vous ne pouvez pas demander directement. Ce sont les méthodes privées.
Pourquoi Rust fait ça
Section intitulée « Pourquoi Rust fait ça »En Rust, tout est privé par défaut, et les méthodes ne font pas exception (voir Les modules). La visibilité appartient au module où le bloc impl est écrit : n’importe quel code de mod bank peut appeler add_interest, et le code à l’extérieur ne le peut pas.
Ça permet à un type de garder de petites méthodes d’aide qui n’ont de sens que dans le bon ordre. Imaginez que add_interest doive s’exécuter une fois par mois, après le prélèvement des frais. Si n’importe qui pouvait l’appeler, quelqu’un finirait par l’appeler deux fois par erreur. Des fonctions d’aide privées, plus une méthode publique qui les exécute correctement, rendent cette erreur impossible.
Ça vous laisse aussi de la liberté. Les méthodes privées peuvent être renommées, fusionnées ou supprimées à tout moment, car le compilateur garantit qu’aucun code extérieur ne s’en sert.
Comment corriger
Section intitulée « Comment corriger »Solution 1 : ajouter pub à la méthode
Section intitulée « Solution 1 : ajouter pub à la méthode »Choisissez-la quand la méthode est faite pour être appelée depuis l’extérieur. Pour new, c’est presque toujours le cas : un constructeur que personne ne peut appeler ne sert pas à grand-chose.
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!("Solde : {}", account.balance());}Sortie :
Solde : 1010Solution 2 : appeler la méthode publique prévue pour vous
Section intitulée « Solution 2 : appeler la méthode publique prévue pour vous »Choisissez-la quand la méthode privée est une fonction d’aide, surtout dans du code que vous n’avez pas écrit. Il existe souvent une méthode publique qui l’appelle pour vous, dans le bon ordre et avec les bonnes vérifications. Ici, garder add_interest privée est la bonne conception :
mod bank { pub struct Account { balance: u64, }
impl Account { pub fn new(opening: u64) -> Account { Account { balance: opening } }
// La porte d'entrée publique : un seul appel fait tout le mois, dans le bon ordre. pub fn close_month(&mut self) { self.charge_fee(); self.add_interest(); }
pub fn balance(&self) -> u64 { self.balance }
// Fonctions d'aide privées : les appeler seules, ou deux fois, donne de faux résultats. 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!("Après un mois : {}", account.balance()); // account.add_interest(); // ❌ E0624: method `add_interest` is private}Sortie :
Après un mois : 1004Une bonne règle : ne rendez une méthode pub que si l’appeler seule, à n’importe quel moment, ne peut pas casser la struct. Si elle n’a de sens que comme une étape d’une opération plus grande, gardez-la privée et exposez l’opération plus grande.
Solution 3 : utiliser pub(crate) pour « mon code seulement »
Section intitulée « Solution 3 : utiliser pub(crate) pour « mon code seulement » »Choisissez-la quand d’autres modules de votre crate ont besoin de la méthode, mais pas les personnes qui utilisent votre bibliothèque. pub(super) (seulement le module parent) fonctionne de la même façon ; la page E0603 contient un tableau de tous les niveaux.
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); }
// Pour notre propre code seulement (comme les tickets de caisse), pas pour les utilisateurs de la bibliothèque. 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);}Sortie :
Total : 8Un piège : dans un paquet qui contient à la fois src/lib.rs et src/main.rs, ce sont deux crates. Une pub(crate) fn total dans lib.rs est privée pour 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 hereRustc dit que la méthode total est privée, et montre sa définition dans src/lib.rs. Dans ce cas, utilisez un simple pub. Voir Cargo et les crates.
Solution 4 : déplacer dans le module le code qui en a besoin
Section intitulée « Solution 4 : déplacer dans le module le code qui en a besoin »Choisissez-la quand la méthode doit vraiment rester privée, mais qu’un certain code en a quand même besoin, comme une vérification d’audit ou un test. Le code du même module peut l’appeler, et un module enfant aussi : les modules à l’intérieur de bank voient tout ce qui est privé dans 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 } }
// Un module enfant peut utiliser tout ce qui est privé dans son parent. pub mod audit { pub fn check(account: &super::Account) -> &'static str { if account.is_suspicious() { "à vérifier" } else { "ok" } } }}
fn main() { let small = bank::Account::new(500); let big = bank::Account::new(50_000); println!("petit : {}", bank::audit::check(&small)); println!("gros : {}", bank::audit::check(&big));}Sortie :
petit : okgros : à vérifierLes tests unitaires fonctionnent de la même façon. Un mod tests écrit à l’intérieur de bank (ou en bas de src/bank.rs) est un module enfant : il peut donc appeler les méthodes privées. Voir Les tests :
#[cfg(test)]mod tests { use super::*;
#[test] fn not_suspicious_when_small() { let account = Account::new(500); assert!(!account.is_suspicious()); // privée, mais autorisée ici }}Où vous le verrez souvent
Section intitulée « Où vous le verrez souvent »Un bloc impl dans un autre module. La visibilité appartient au module où l’impl est écrit, pas à la struct. Si Order vit dans mod model mais que vous écrivez impl Order { fn with_tax(&self) ... } dans mod pricing, alors main obtient method `with_tax` is private, avec une flèche vers mod pricing. Correction : pub fn with_tax, ou pub(crate).
Utiliser une méthode comme valeur de fonction. accounts.iter().map(bank::Account::audit) est le même appel, écrit autrement, et donne donc la même E0624. Même correction.
Les méthodes de trait. On n’écrit jamais pub sur les méthodes d’un impl SomeTrait for Type. Elles sont aussi publiques que le trait, et ajouter pub est une erreur : error[E0449]: visibility qualifiers are not permitted here (les qualificatifs de visibilité ne sont pas autorisés ici). Si une méthode de trait semble manquer, vous obtiendrez plutôt E0599, et la correction consiste à importer le trait avec use.
La méthode privée d’une crate. Vous avez trouvé la méthode parfaite dans le code source d’une crate sur GitHub, mais elle n’est pas pub. Vous ne pouvez pas l’appeler, et ses auteurs peuvent la modifier à chaque nouvelle version. Cherchez sur la page de la crate sur docs.rs une méthode publique qui fait le travail ; seuls les éléments pub y apparaissent.
Erreurs liées
Section intitulée « Erreurs liées »- E0603 :
function `x` is private(la fonction est privée). La même idée pour les fonctions libres, les structs et les modules. - E0616 :
field `x` of struct `Y` is private, quand vous lisez ou modifiez un champ. - E0451 : un champ privé au moment de construire une struct avec
Y { ... }. Généralement corrigé par unepub fn new. - E0599 :
no method named `x` found(aucune méthode de ce nom). La méthode n’existe pas pour ce type, ou son trait n’est pas dans la portée. - Toutes les erreurs du compilateur : la liste complète des pages d’erreurs.
Petit quiz
Section intitulée « Petit quiz »Petit quiz
1. pub struct Timer a impl Timer { fn start() -> Timer { ... } } dans mod clock. Que se passe-t-il quand main appelle clock::Timer::start() ?
2. Quel code peut appeler une méthode privée définie dans mod bank ?
3. Une méthode privée add_interest ne doit s'exécuter qu'une fois par mois, après les frais. Quelle est la meilleure correction pour E0624 ?
Score : 0 / 3
Pour aller plus loin
Section intitulée « Pour aller plus loin »- E0624 — Rust error codes index (en anglais) : l’explication officielle, avec un exemple minimal.
- Method Syntax — The Rust Book (en anglais) : les méthodes, les fonctions associées et les blocs
impl. - Paths for Referring to an Item in the Module Tree — The Rust Book (en anglais) : exposer des éléments avec
pub, étape par étape. - Testing Private Functions — The Rust Book (en anglais) : pourquoi les tests unitaires peuvent appeler du code privé.
- Visibility and privacy — The Rust Reference (en anglais) : les règles exactes, y compris
pub(crate),pub(super)etpub(in path).