`Pub` destina-se a indicar público para engradado ou público para módulo? [duplicado]

Dec 15 2020

Para tornar os métodos de um submódulo público, você deve reexportá-los explicitamente ou então tornar o próprio submódulo público:

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

Isso parece indicar que pubé usado para indicar que algo deve ser público apenas para um módulo (já que você pode optar por não fazer isso)

Mas se você usar um tipo privado definido no contexto externo, obterá um erro se tentar tornar uma função pública envolvendo-o pública no contexto interno, mesmo quando não for reexportado.

mod foo {
    struct Foo;

    mod bar {
        use super::Foo;

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

resulta em

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

Qual é a maneira idiomática de usar a pubpalavra - chave? Deve ser reservado para coisas que são realmente públicas ou pode ser usado para módulos internos?

Respostas

2 vallentin Dec 15 2020 at 04:06

A razão pela qual seu exemplo falha ao compilar é, em última análise, porque a RFC (136) disse isso. (Veja também o problema 22261 )

Que restrições se aplicam a itens públicos?

As regras para vários tipos de itens públicos são as seguintes:

  • Se for uma staticdeclaração, os itens mencionados em seu tipo devem ser públicos.
  • Se for uma fndeclaração, os itens mencionados em seus limites de característica, tipos de argumento e tipo de retorno devem ser públicos.
  • Se for uma declaração structou enum, os itens mencionados em seus limites de característica e nos tipos de seus pubcampos devem ser públicos.
  • Se for uma typedeclaração, os itens mencionados em sua definição devem ser públicos.
  • Se for uma traitdeclaração, os itens referidos em seus super-traços, nos limites dos traços de seus parâmetros de tipo e nas assinaturas de seus métodos (veja o fncaso acima) devem ser públicos.

Em suma, baznão é permitido pubporque tem um argumento que é do tipo privado. Assim, se bazfor pub, permitiria que o pai mod fooreexportasse bazfazendo pub use bar::baz;. É claro que isso não é permitido, e é por isso que o exemplo como um todo é ilegal.

Alguns mencionaram anteriormente que isso pub fn bazdeveria ser permitido e, em vez disso, fornecer um erro de compilação no caso de o módulo pai exportá-lo novamente. No entanto, isso exigiria uma análise estática mais complexa para detectar e, em última análise, não foi feito porque a RFC definiu que é ilegal.


pubespecifica que o item pode ser acessado pelo módulo pai. Se todos os ancestrais do módulo forem pub, esse item será exportado pela caixa como um todo.

A palavra-chave pubtorna qualquer módulo, função ou estrutura de dados acessível de dentro de módulos externos. A pubpalavra-chave também pode ser usada em uma usedeclaração para reexportar um identificador de um namespace.

- Documentação de ferrugem

Com a noção de um item ser público ou privado, Rust permite acessos a itens em dois casos:

  1. Se um item for público, ele pode ser acessado externamente de algum módulo m se você puder acessar todos os módulos ancestrais do item de m. Você também pode potencialmente nomear o item por meio de reexportações. Ver abaixo.
  2. Se um item for privado, ele pode ser acessado pelo módulo atual e seus descendentes.

- The Rust Reference - Visibilidade e Privacidade