¿"Pub" está destinado a indicar de público a caja o de público a módulo? [duplicar]

Dec 15 2020

Para hacer públicos los métodos de un submódulo, debe reexportarlos explícitamente o, de lo contrario, hacer público el submódulo:

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

Esto parece sugerir que pubse usa para indicar que algo debería ser público solo para un módulo (ya que puede elegir no hacer esto)

Pero si usa un tipo privado definido en el contexto externo, obtendrá un error si intenta hacer pública una función pública que lo involucre en el contexto interno incluso cuando no se reexporta.

mod foo {
    struct Foo;

    mod bar {
        use super::Foo;

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

resultados 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

¿Cuál es la forma idiomática de usar la pubpalabra clave? ¿Debería reservarse para cosas que son realmente públicas o se puede utilizar para módulos internos?

Respuestas

2 vallentin Dec 15 2020 at 04:06

La razón por la que su ejemplo no se compila es, en última instancia, porque el RFC (136) lo dice. (Ver también el número 22261 )

¿Qué restricciones se aplican a los artículos públicos?

Las reglas para varios tipos de elementos públicos son las siguientes:

  • Si se trata de una staticdeclaración, los elementos a los que se hace referencia en su tipo deben ser públicos.
  • Si se trata de una fndeclaración, los elementos a los que se hace referencia en sus límites de características, tipos de argumentos y tipo de retorno deben ser públicos.
  • Si es una declaración structo enum, los elementos a los que se hace referencia en sus límites de características y en los tipos de sus pubcampos deben ser públicos.
  • Si se trata de una typedeclaración, los elementos a los que se refiere su definición deben ser públicos.
  • Si se trata de una traitdeclaración, los elementos a los que se hace referencia en sus super-rasgos, en los límites de los rasgos de sus parámetros de tipo y en las firmas de sus métodos (ver fncaso anterior) deben ser públicos.

En resumen, bazno está permitido pubporque tiene un argumento que es de tipo privado. Por lo tanto, si bazes pubasí, permitiría al padre mod fooreexportar bazhaciendo pub use bar::baz;. Por supuesto, esto no está permitido, y esta es la razón por la que el ejemplo en su conjunto es ilegal.

Algunos han mencionado anteriormente que pub fn bazdebería permitirse y, en cambio, dar un error de compilación en caso de que el módulo padre lo reexporta. Sin embargo, eso requeriría un análisis estático más complejo para detectar y, en última instancia, no se ha realizado porque el RFC definió que es ilegal.


pubespecifica que el módulo principal puede acceder al elemento. Si todos los antepasados ​​del módulo lo son pub, entonces la caja exporta ese elemento como un todo.

La palabra clave pubhace que cualquier módulo, función o estructura de datos sea accesible desde el interior de módulos externos. La pubpalabra clave también se puede utilizar en una usedeclaración para reexportar un identificador de un espacio de nombres.

- Documentación de óxido

Con la noción de que un elemento es público o privado, Rust permite el acceso al elemento en dos casos:

  1. Si un elemento es público, entonces se puede acceder externamente desde algún módulo m si puede acceder a todos los módulos ancestros del elemento desde m. También puede potencialmente poder nombrar el artículo mediante reexportaciones. Vea abajo.
  2. Si un elemento es privado, el módulo actual y sus descendientes pueden acceder a él.

- The Rust Reference - Visibilidad y privacidad