«Pub» est-il censé indiquer public-to-crate ou public-to-module? [dupliquer]

Dec 15 2020

Pour rendre publiques les méthodes d'un sous-module, vous devez les réexporter explicitement ou bien rendre le sous-module lui-même public:

mod foo {
    mod bar {
        pub fn baz() {}
    }
    pub use self::bar::baz;
}

Cela semble indiquer qu'il pubest utilisé pour indiquer qu'une chose doit être publique uniquement pour un module (puisque vous pouvez choisir de ne pas le faire)

Mais si vous utilisez un type privé défini dans le contexte externe, vous obtenez une erreur si vous essayez de rendre publique une fonction publique l'impliquant dans le contexte interne, même si elle n'est pas réexportée.

mod foo {
    struct Foo;

    mod bar {
        use super::Foo;

        pub fn baz(foo: Foo) {}
    }
}

résulte en

error[E0446]: private type `Foo` in public interface
 --> src/lib.rs:7:9
  |
2 |     struct Foo;
  |     - `Foo` declared as private
...
7 |         pub fn baz(foo: Foo) {}
  |         ^^^^^^^^^^^^^^^^^^^^ can't leak private type

Quelle est la manière idiomatique d'utiliser le pubmot-clé? Doit-il être réservé aux choses qui sont réellement publiques ou peut-il être utilisé pour des modules internes?

Réponses

2 vallentin Dec 15 2020 at 04:06

La raison pour laquelle votre exemple ne parvient pas à se compiler est finalement parce que la RFC (136) l'a dit. (Voir aussi le numéro 22261 )

Quelles restrictions s'appliquent aux objets publics?

Les règles applicables aux différents types d'objets publics sont les suivantes:

  • S'il s'agit d'une staticdéclaration, les éléments mentionnés dans son type doivent être publics.
  • S'il s'agit d'une fndéclaration, les éléments auxquels il est fait référence dans ses limites de trait, ses types d'argument et son type de retour doivent être publics.
  • S'il s'agit d'une déclaration structou enum, les éléments auxquels il est fait référence dans ses limites de trait et dans les types de ses pubchamps doivent être publics.
  • S'il s'agit d'une typedéclaration, les éléments visés dans sa définition doivent être publics.
  • S'il s'agit d'une traitdéclaration, les items référencés dans ses super-traits, dans les limites de ses paramètres de type et dans les signatures de ses méthodes (voir fncas ci-dessus) doivent être publics.

En bref, il bazn'est pas permis d'être pubcar il a un argument qui est un type privé. Ainsi, si bazc'est le cas, pubcela permettrait au parent mod foode réexporter bazen faisant pub use bar::baz;. Ceci n'est bien sûr pas autorisé, et c'est la raison pour laquelle l'exemple dans son ensemble est illégal.

Certains ont précédemment mentionné que cela pub fn bazdevrait être autorisé, et à la place de donner une erreur de compilation dans le cas où le module parent le réexporte. Cependant, cela nécessiterait une analyse statique plus complexe pour détecter, et n'a finalement pas été fait parce que la RFC a défini qu'il est illégal.


pubspécifie que l'élément est accessible par le module parent. Si tous les ancêtres du module le sont pub, alors cet élément est exporté par la caisse dans son ensemble.

Le mot-clé pubrend tout module, fonction ou structure de données accessible depuis l'intérieur des modules externes. Le pubmot clé peut également être utilisé dans une usedéclaration pour réexporter un identifiant à partir d'un espace de noms.

- Documentation sur la rouille

Avec la notion d'élément public ou privé, Rust autorise les accès aux éléments dans deux cas:

  1. Si un élément est public, alors il peut être accédé en externe à partir d'un module m si vous pouvez accéder à tous les modules ancêtres de l'élément à partir de m. Vous pouvez également potentiellement nommer l'élément via des réexportations. Voir ci-dessous.
  2. Si un élément est privé, il est accessible par le module actuel et ses descendants.

- The Rust Reference - Visibilité et confidentialité