Rust: (Módulos) Problema de seguimiento de `caja` como modificador de visibilidad

Creado en 6 ago. 2018  ·  91Comentarios  ·  Fuente: rust-lang/rust

Este es un problema de seguimiento secundario para el RFC "Aclarar y simplificar rutas y visibilidad" (rust-lang/rfcs#2126)
tratando la cuestión de crate como modificador de visibilidad.

Preguntas sin resolver:

  • [ ] ¿Cómo analizamos struct Foo(crate ::bar) ?
A-visibility B-RFC-approved B-RFC-implemented B-unstable C-tracking-issue T-lang

Comentario más útil

Personalmente, estoy de acuerdo con escribir pub(crate) , la intención parece muy explícita.
El ejemplo dado por @johnthagen es realmente doloroso de ver (usando crate ):

use crate::menu::{Sound, Volume};

crate mod color;

...

/// A type for storing text and an associated color it should
/// be drawn as.
crate struct ColoredText {
    crate color: types::Color,
    crate text: &'static str,
}

crate mod color; parece especialmente confuso, definitivamente debes pensar un poco en lo que está sucediendo allí.

Todos 91 comentarios

Comentarios sobre crate como modificador de visibilidad:

Análisis de ambigüedad

Antinatural / Confusión / No mejora

Una buena idea

pub(extern) en su lugar

cobertizo para bicicletas

Una vista previa temprana

Hilo dedicado

Personalmente, estoy muy a favor de crate como modificador de visibilidad y comparto el comentario de @stepancheg aquí . Creo que deberíamos fomentar visibilidades más pequeñas y estrictas y crate hace exactamente eso.

Personalmente, estoy de acuerdo con escribir pub(crate) , la intención parece muy explícita.
El ejemplo dado por @johnthagen es realmente doloroso de ver (usando crate ):

use crate::menu::{Sound, Volume};

crate mod color;

...

/// A type for storing text and an associated color it should
/// be drawn as.
crate struct ColoredText {
    crate color: types::Color,
    crate text: &'static str,
}

crate mod color; parece especialmente confuso, definitivamente debes pensar un poco en lo que está sucediendo allí.

Algunos de estos ejemplos son muy C- static -esque- intuitivamente relacionados pero realmente sorprendentemente distintos.

El ejemplo debido a @johnthagen no me parece mal. De hecho, se lee con naturalidad y me gusta bastante la simetría. Es hermoso en cierto modo.

Si la legibilidad de:

crate struct ColoredText {
    crate color: types::Color,
    crate text: &'static str,
}

se convierte en un problema; luego, un IDE/editor que comprenda la sintaxis de Rust puede resaltar los tokens crate en las diferentes posiciones con diferentes colores. Creo que eso debería aclarar la diferencia.

crate como modificador de visibilidad es definitivamente extraño: usa una palabra clave muy específica de óxido para algo que no es específico de óxido. Kotlin y C# usan internal para esto.

Personalmente, me gustaría reutilizar pub por crate-visible , y optar por una sintaxis más llamativa para el mundo visible, como pub* o pub! .

Se ha mencionado antes, pero creo que los problemas de raíz que veo son:

  1. crate es un sustantivo . Creo que pub(crate) es largo y de aspecto extraño, por lo que apoyo totalmente reemplazarlo con algo , pero tenía el adjetivo público asociado, por lo que fluyó mejor gramaticalmente.
  2. crate ahora se usa como el ancla para las importaciones de "esta caja", lo que significa algo diferente a "dondequiera que se defina, también se exporta visiblemente desde esta caja".
// Here `crate` means the root of this crate.
use crate::menu::{Sound, Volume};

// Here, `crate` means: export crate::game::color
// The `crate` is referring to `color`, not the root.
crate mod color;

...

/// A type for storing text and an associated color it should
/// be drawn as.
// Same potential confusion as `crate mod color`
crate struct ColoredText {
    crate color: types::Color,
    crate text: &'static str,
}

Comparado con un ejemplo, usando internal de @matklad de Kotlin/C#.

use crate::menu::{Sound, Volume};

internal mod color;

...

/// A type for storing text and an associated color it should
/// be drawn as.
internal struct ColoredText {
    internal color: types::Color,
    internal text: &'static str,
}

No estoy diciendo que internal sea la palabra clave correcta (a Rust le gustan las abreviaturas muy cortas, y int desafortunadamente está lleno de confusión de C/C++/Java), pero personalmente creo que el segundo ejemplo es inmediatamente más legible.

También creo que la palabra clave de visibilidad crate será confusa para las personas que vienen a Rust desde otros idiomas. Si incluso muchos de los que estamos lo suficientemente involucrados en Rust como para comentar en estos hilos estamos molestos, tengo que imaginar que también hará tropezar a las personas nuevas en Rust.

La sintaxis un poco más larga de pub(crate) puede no ser tan importante si no se convirtiera en una advertencia/error de tener pub elementos que no son accesibles fuera de la caja. Personalmente, desearía que si tuviera un pub(crate) struct Foo { ... } , el compilador pudiera darse cuenta de que todos los pub fn en un impl Foo claramente no son accesibles, y no me molestaría por eso.

Me parece que es un trabajo ocupado actualmente en Rust 2015 si alguna vez marco un tipo de pub struct Foo a pub(crate) struct Foo , cómo el compilador grita en todos los lugares que otros pub fn s existen usando el tipo repentinamente pub(crate) , cuando el problema no es real, porque el otro tipo también es pub(crate) .

También encuentro la idea de @matklad de reutilizar pub como caja pública y usar export o algo así para exportaciones visibles en todo el mundo. ¿Pero eso puede ser una divergencia demasiado grande para una edición?

Reutilizar pub como crate-public y agregar una nueva visibilidad para world-public fue la propuesta anterior a la versión actual. Tal cambio en la semántica existente se consideró demasiado drástico incluso para una edición, razón por la cual pub ahora mantiene su significado actual.

Creo que lo que se discutió y consideró menos fue la reutilización pub únicamente a través de una pelusa. Tal vez podríamos cambiar la pelusa de "advertir en pub que no es accesible fuera de la caja" a "advertir en pub que es accesible fuera de la caja" y agregar un pub(extern) puramente opcional pub(extern) / export palabra clave. Es decir, no cambie ninguna semántica, solo agregue una sintaxis de silenciamiento de pelusa.

Sospecho que esto sería menos disruptivo, basado en la suposición de que hay menos elementos públicos mundiales que elementos públicos de cajas. También preservaría el significado intuitivo (aunque sutilmente incorrecto) de pub como "exportar desde el módulo actual" en lugar de confrontar a todos con el verdadero comportamiento de la visibilidad.

A Rust le gustan las abreviaturas muy cortas, y int lamentablemente está lleno de confusión de C/C++/Java

FWIW, aunque solo guarda dos caracteres, si quisiéramos abreviar internal , la abreviatura "correcta" probablemente sería, por analogía con extern al, intern . Lamentablemente, ese también es un sustantivo con un significado diferente comúnmente entendido. Oh bien.

¡@glaebhoerl intern es una buena opción a considerar! ❤️

La simetría con extern es realmente agradable y, en mi opinión, reduciría en gran medida la posible confusión con la forma nominal de intern .

Es corto (solo 1 carácter más que crate ) y no choca con use crate:: .

El ejemplo actualizado se vería así:

use crate::menu::{Sound, Volume};

intern mod color;

...

/// A type for storing text and an associated color it should
/// be drawn as.
intern struct ColoredText {
    intern color: types::Color,
    intern text: &'static str,
}

Lo he mencionado antes, pero no estoy seguro de cuál es el problema con los sustantivos que se usan como adjetivos.

En resumen: hay muchos sustantivos que se pueden usar como adjetivos, por ejemplo. un gato doméstico, un mouse de computadora, un escritorio de computadora, etc. Una búsqueda en Google de _sustantivos en inglés usados ​​como adjetivos_ parece indicar que no hay nada intrínsecamente malo, aunque no todos los sustantivos funcionan como adjetivos.

Vamos a intentarlo:

_crate mod hola;_ Un módulo de caja llamado hola, se siente bien.
_crate fn world() {}_ Una función de caja llamada mundo, se siente bien.
_crate struct Foo;_ Una estructura de caja llamada Foo, se siente bien.
_crate enum Bar {}_ Una enumeración de caja llamada Bar, se siente bien.
_rasgo de caja Baz {}_ Un rasgo de caja llamado Baz, se siente bien.

_crate use self::local::Foo;_ Ack, este no funciona, ¿un uso de caja? Puede leerlo como un elemento utilizable de caja llamado Foo. Rompe el patrón.

También puede ser incómodo cuando se usa frente a los miembros de la estructura y aún más en combinación con la caja como la raíz de un camino.

Si bien crate no es perfecto, no estoy convencido de que 'ser un sustantivo' sea un factor decisivo.

El problema es que es muy raro. No conozco ningún lenguaje de programación que use sustantivos como modificador de tipo.

@centril

se convierte en un problema; luego, un IDE/editor que comprenda la sintaxis de Rust puede resaltar los tokens de caja en las diferentes posiciones con diferentes colores. Creo que eso debería aclarar la diferencia.

Personalmente, si bien encuentro agradables las características de diferentes editores, no creo que debamos diseñar el lenguaje con la suposición de un editor suficientemente avanzado. Sentí que C# se diseñó de esta manera y fue un factor importante en mi frustración con ese lenguaje.

@epage Creo que crate como modificador de visibilidad es una buena idea independientemente del resaltado; Simplemente estoy sugiriendo que resaltar es una mitigación adicional . En particular, debería ser bastante trivial para cualquier editor resaltar crate:: de manera diferente a crate field porque el primero siempre es crate + :: lo cual es fácil de verificar. para en todos los casos excepto crate ::foo::bar (pero esto será bastante raro...).

Como persona de IDE, creo que tal resaltado agregaría una cantidad significativa de ruido para una cantidad muy pequeña de información, lo que resultaría negativo. En mi opinión (esto es muy personal, pero se basa tanto en el uso como en la implementación de potentes IDE) el resaltado funciona mejor cuando transmite información semántica no local (¿este uso se refiere a una variable que se declaró con mut ) y de enfatiza aspectos locales del código "calendario" (por lo que todas las palabras clave deben tener exactamente el mismo estilo).

Me parece que dom (es decir, nacional) es un candidato potencial.

Tiene tres letras (agradable para la alineación, fácil de recordar), no es un sustantivo y, aparte de 'Modelo de objeto de documento', no creo que tenga ninguna ambigüedad en particular.

pub struct MyStruct {
    dom num: i32,
    pub msg: String,
}

¿Alguien tiene pensamientos sobre esto?

Un ángulo sobre esto que he visto mencionado pero que no pude encontrar en el resumen (¡gracias por hacerlo por cierto!) es cómo un atajo encaja con la sintaxis pub() existente.

Si pub y <something> (por ejemplo crate ) tienen un significado especial, reduce aún más la visibilidad y, por extensión, la familiaridad de pub(<something>) . Cualquiera que sea la solución que elijamos, creo que debería respaldar o reemplazar la maquinaria existente en lugar de ser otra más.

Por ejemplo, si usamos crate o reemplazo:

  • ¿Debería extenderse crate para asumir restricciones de alcance (por ejemplo crate(<something>) )?
  • ¿Deberíamos desaprobar pub() para que pub solo tenga un significado?

Teniendo en cuenta esto y mi comprensión del objetivo (aclarar la API pública de la API interna), me llevó a recrear la idea de @vitiral de pub(extern) .

  • Se adapta a la maquinaria existente
  • imo mejora la maquinaria existente haciendo que pub sea un atajo de pub(<something>) en lugar de ser un caso especial
  • Si la API pública es significativamente más pequeña que la API privada, hemos ponderado la sintaxis de la manera correcta.
  • Pero podría confundir a las personas que vienen de otros idiomas donde public significa que podría estar en su API pública.

RE Impacto en la encapsulación

Una de las ventajas del sistema pub existente es la encapsulación. El camino fácil es exponer la API solo un nivel hacia arriba. Esto hace que sea más fácil tener cosas públicas para partes de una caja pero privadas para toda la creación.

Si bien todavía habrá pub(super) , tener un atajo para pub(crate) empujará a las personas en la dirección de usarlo más, alentando a las personas a no encapsular sus API.

Sospecho que esto no es un problema debido a la cultura de las cajas pequeñas.

Pero al considerar esto, me da otra iteración en mi comentario anterior sobre pub(extern)

  • pub debería ser un atajo para pub(super)
  • Se requiere pub(extern) para su API pública.

Anteriormente mencioné la preocupación de las personas que hacen la transición de otros idiomas. Esto se alinea mejor con ellos.

  • Coincide más estrechamente con el funcionamiento public en varios idiomas
  • Algunos lenguajes tienden a tener un mecanismo distinto para la API pública, por lo que esto se les puede explicar.

En mi opinión, este es el mejor de todos los mundos. Así que destrúyelo y ayúdame a entender por qué no :)

Todavía odio la sintaxis pub(foo) . Hiperbólicamente, parece que no puede decidir si es una llamada de función o una combinación de varias palabras clave. No usamos let(mut) o for(in) entonces, ¿cuál es el problema con este?

¡@parasyte pub<foo> por la victoria! Después de todo, ¿no es un _tipo de visibilidad_?

pub<crate> o pub(crate) realmente me siento mejor.

Algunos pensamientos de alguien que cambió de campamento:

Al principio me opuse mucho a crate y pensé "esto está arruinando el buen pub ".

Luego lo probé en paralelo en algunos de mis proyectos y lo dejé asimilar.

Francamente, después de unos días ya no podía soportar mirar pub(X) , se siente torpe en comparación y más difícil de leer.

Inicialmente, temía que pudiera haber ambigüedad (visual); pero a mí me sucedió lo contrario: si veo crate ahora sé que es, bueno, "cosas de caja". Ya sea importando módulos o declarando visibilidad. Qué es exactamente en la abrumadora mayoría de los casos muy claro por el contexto (una especie de ambigüedad en inglés).

Puedo ver que todavía puede haber una ambigüedad residual "más dura" (visual) en algunos casos, pero no me gustaría cambiar eso por lo que ahora se siente como una ganancia masiva de legibilidad cuantitativa (como en: "líneas de código fuente que requieren menos tokenización/esfuerzo visual frente a líneas de código fuente que se volvieron más ambiguas").

Desde ese ángulo crate - intern (o cualquier otra asimetría) también se sentiría como un paso atrás.

Habiendo dicho esto, no sé cómo analizar la ambigüedad. Si tuviera que elegir uno, preferiría tener una buena historia sobre " crate significa cosas de cajas" que una buena historia sobre " crate ::foo::bar simplemente funciona".

Mis dos centavos son que:

  • He estado usando crate mod , crate struct , crate fn , ... mucho y lo encuentro extremadamente útil.
  • Realmente no me importa cómo se llame ( crate , pub(crate) , ...) siempre y cuando no sea demasiado largo porque lo uso a menudo.

Si fuera por mí, usaría vis como palabra clave y el tipo de visibilidad como modificador, por ejemplo, vis(pub) , vis(crate) , etc. porque esto hace más sentido para mi

Dado que ya estamos atascados con pub como "especificador de visibilidad", en realidad me gusta crate . El pub(crate) se lee para mí como público para este módulo, privado para la caja. Encuentro que usar público y privado al mismo tiempo aquí es extraño.

Introducir nuevas palabras clave y palabras clave contextuales, etc., en mi opinión, no vale la pena. Enseñar que hay dos modificaciones de visibilidad pub y crate , y que uno significa público y el otro significa privado para la caja, tiene sentido para mí, pero tal vez me acostumbré crate ya durante las últimas dos semanas.

Para aquellos que sugieren que una palabra clave ya utilizada (es decir, crate ) combina significados, diría que el contexto es más importante que la palabra misma. El cerebro analiza todo con contexto (cómo el compilador analiza esto es un asunto diferente): esto explica por qué no combinamos el significado semántico de for en for x in y y impl X for Y .

Del mismo modo, la introducción crate como un calificador de visibilidad probablemente no crearía confusión porque su significado, en el contexto de un miembro o calificador de función, es obvio cuando se proporciona con ese contexto adicional. Por ejemplo, crate fn my_func(); no se lee como "esto es una caja", se lee como "esta es una función visible en la caja".

Dicho esto, el hecho de que sea un sustantivo es inconsistente. Yo estaría a favor de crear una nueva palabra clave calificadora de visibilidad para abordar este problema.

De hecho, si hay algo que definitivamente confundirá a los usuarios, es la sintaxis pub(crate) que intuitivamente parece una llamada de función y no tiene otro equivalente sintáctico en ninguna otra parte del lenguaje. Para mí, se siente como un truco feo.

Como alguien que ha planteado preocupaciones sobre el uso crate como reemplazo de pub(crate) y después de leer la última publicación de @aturon :

Caja de soporte como modificador de visibilidad (seguido aquí 138) . Dados los comentarios hasta ahora, es poco probable que esta función se estabilice para Rust 2018 .

Solo quiero asegurarme de tener claro que personalmente estoy totalmente a favor de reemplazar pub(crate) con algo (como creo que es la mayoría).

En orden de preferencia, con lo que creo que sería más fácil de entender, especialmente para aquellos nuevos o no familiarizados con Rust:

  1. intern (o alguna otra palabra clave nueva similar)
  2. crate
  3. pub(crate)

Si el equipo central siente que intern o algo similar finalmente nunca sería aceptado, entonces me quedaría atrás crate ya que sigo pensando que es una gran mejora con respecto a pub(crate) , por las razones que @Centril y otros han articulado.

Así que no me interpondría en el camino de esto si el equipo central, mucho más experimentado, siente que este es el mejor camino a seguir. Es bueno poder proporcionar comentarios, expresar ideas para su consideración. 👍 ¡Óxido!

@ralfbiedert

Inicialmente, temía que pudiera haber ambigüedad (visual); pero a mí me sucedió lo contrario: si veo una caja ahora, sé que es, bueno, "cosas de una caja". Ya sea importando módulos o declarando visibilidad. Qué es exactamente en la abrumadora mayoría de los casos muy claro por el contexto (una especie de ambigüedad en inglés).

@zesterer

Para aquellos que sugieren que una palabra clave ya utilizada (es decir, caja) combina significados, diría que el contexto es más importante que la palabra en sí. El cerebro analiza todo con contexto (cómo el compilador analiza esto es un asunto diferente): esto explica por qué no combinamos el significado semántico de for in for x in y e impl X for Y.

No pretendo llamarlos personalmente, sino servir como ejemplos de las personas a favor del cambio después de usarlo.

Si bien me parece extraño, mi mayor preocupación son los no rustáceos.

  • ¿Cómo podría afectar esto la opinión de alguien al evaluar el óxido? Una peculiaridad de la sintaxis no debería ser suficiente para disuadirlos, pero si la acumulas con vidas y cualquier otra cosa "extraña", podría desanimar a las personas.
  • ¿Cómo afecta esto a las personas que aprenden Rust?
  • ¿Cómo afecta esto a las personas que no conocen Rust pero necesitan modificarlo?

Me encantaría que pudiéramos hacer estudios de usabilidad sobre esto para saber mejor cuánto impacto tienen estas preocupaciones.

@epage , muy de acuerdo, las partes de Rust orientadas al usuario deben probarse UX. Sin embargo, creo que esto es lo que está sucediendo en este momento, y estamos en medio de la discusión de los resultados.

Para agregar a eso, algunas observaciones anecdóticas de nuestra empresa:

Soy el "defensor de la oxidación" en nuestro departamento y trabajo con otras 3 personas. Todos tienen una sólida formación en C#, pero son relativamente nuevos en Rust. El otro día migré nuestro proyecto de investigación a Rust 2018, junto con el " crate -cosas".

Cuando revisamos el código, las conversaciones fueron aproximadamente así:

"Así que aquí hay algunos otros cambios que hice; nuevo sistema de importación; modificadores".

"¿Qué hace eso?" (señalando use crate::object y crate x: object )

"Importar desde esta caja". y "Modificador de visibilidad".

"Ah, está bien. ¿Algo más que haya cambiado?"

Fin de la discusión.

Seguramente, hablamos un poco más sobre las nuevas características y si deberíamos adoptar ciertos patrones; pero el "aspecto de enseñanza" de estos dos elementos se redujo a unas pocas palabras y no se ha mencionado desde entonces (que yo sepa).

Si escucho algo más la próxima vez que hablemos, actualizaré este comentario.

@ralfbiedert ¡ Gracias por compartir eso!

@epage , muy de acuerdo, las partes de Rust orientadas al usuario deben probarse UX. Sin embargo, creo que esto es lo que está sucediendo en este momento, y estamos en medio de la discusión de los resultados.

Si bien valoro estas anécdotas de UX, especialmente por el lado de la capacidad de aprendizaje, no creo que califique el proceso de este problema como prueba de UX. Mi comentario se refiere a un proceso más formal que puede ayudar a obtener una comprensión más profunda, eliminar sesgos, etc.

Aquí hay algunos pensamientos provenientes de un Rust algo novato. En primer lugar, quiero decir que algo que realmente se siente cuerdo y agradable con este lenguaje es el enfoque "inmutable por defecto, privado por defecto".

Ahora, pub está bien porque es simple y esperado en lenguajes modernos. Siento que tener que desaprender esto en el contexto de Rust y esparcir otra palabra clave en todas partes es un poco torpe. Semánticamente, parece correcto que signifique "este es un botón que aparece en el cuadro", siendo el cuadro el módulo: visibilidad "desde un nivel superior".

Entonces, para mí, usar crate u otra palabra clave de esa naturaleza en lugar de pub simplemente me pica: si ser público no es el valor predeterminado, exportarlo fuera de la caja debería ser aún más especial. . Es decir, la API de la caja debe indicarse de una manera especial.

Por lo tanto, estoy totalmente de acuerdo con @epage , pub debe permanecer igual y se debe introducir un pub(extern) de algún tipo. Sin embargo, las palabras clave entre paréntesis realmente se sienten peludas, por lo que tal vez merezcan una palabra clave dedicada. La palabra clave crate funcionaría en ese sentido, puedo ver que significa "este es un miembro de caja exportado". O export en realidad, no lo sé. Sin embargo, tal vez todo mi punto se deba a un problema, y ​​todo esto equivale a "las palabras clave no son correctas". Pero pub es tan común que no se siente especial, por lo que no debería representar algo realmente especial (la API exportada por caja).

Vi una charla en RustConf este fin de semana que usó una gran cantidad de pub(crate) en sus ejemplos de código, y realmente me hizo desear el antiguo crate . Todavía estoy muy a favor del plan original.

@steveklabnik

Vi una charla en RustConf este fin de semana que usó mucho pub (caja) en sus ejemplos de código, y realmente me hizo desear una caja simple y antigua. Todavía estoy muy a favor del plan original.

¿El contexto de este comentario es principalmente de RustConf o tiene en cuenta este hilo y presupone un desacuerdo con él? Anteriormente, proporcioné una solución alternativa, no para pub(crate) sino para los requisitos que impulsan cualquiera de los cambios de pub y espero que satisfaga las necesidades de las personas.

Ver

@superseed

Por lo tanto, estoy totalmente de acuerdo con @epage , el pub debe permanecer igual y se debe introducir un pub (externo) de algún tipo. Sin embargo, las palabras clave entre paréntesis realmente se sienten peludas, por lo que tal vez merezcan una palabra clave dedicada. La palabra clave crate funcionaría en ese sentido, puedo ver que significa "este es un miembro de caja exportado". O exportar en realidad, no lo sé. Sin embargo, tal vez todo mi punto se deba a un problema, y ​​todo esto equivale a "las palabras clave no son correctas". Pero el pub es tan común que no se siente especial, por lo que no debería representar algo realmente especial (la API exportada por caja).

RE "Sin embargo, las palabras clave entre paréntesis realmente se sienten peludas"

Si bien personalmente pensé que eran geniales cuando me enteré de ellos (mucho mejor que todo o nada friend ), mi mayor preocupación es que no creamos una sintaxis paralela sino que aceptamos lo que tenemos o encontramos una solución alternativa

Por otro lado...

RE O export en realidad,

No creo que agregar export contradiga mi comentario anterior en contraste con crate . En este contexto, export podría tratarse como algo diferente a la visibilidad. export implicaría pub(crate) . Sospecho que esto no tendrá mucho problema en la enseñanza.

Puedo ir de cualquier manera en esta extensión de mi idea original.

@superseed

pub […] visibilidad "desde un nivel hacia arriba".
La palabra clave crate funcionaría en ese sentido, puedo ver que significa "este es un miembro de caja exportado".

Creo que su comprensión del significado de estas dos palabras clave puede ser exactamente lo contrario de lo que se propone aquí, que es que pub significa público para todos, mientras que crate significa accesible desde la misma caja.

@epage

En el caso de pub(crate) , ofrece una función realmente interesante y, de hecho, se lee bien, pero se parece demasiado a una llamada de función en mi opinión. es decir, sin el resaltado sintáctico, probablemente estaría realmente confundido, y el resaltado no debería ser necesario para comprender la semántica de un idioma.

@SimonSapin

De hecho, y me doy cuenta de que esa es la forma en que se supone que debe entenderse, pero crate , al ser un sustantivo, se siente como si estuviera declarando una caja (?) o una propiedad de la caja. Énfasis en declarar y no calificar.

Y public / pub es un calificador tan omnipresente que no me parece (¡para mí!) que deba significar "esto se exporta fuera de la caja". Tiene este significado de "esto es visible desde fuera del contexto en el que estoy", como es el caso de su uso para calificar la visibilidad de miembros struct (y corríjame si me equivoco pero no No creo que la semántica esté cambiando en ese caso).

Y public/pub es un calificador tan ubicuo que no se siente (¡para mí!) Como que debería significar "esto se exporta fuera de la caja". Tiene este significado de "esto es visible desde fuera del contexto en el que estoy", como es el caso de su uso para calificar la visibilidad de los miembros de la estructura (y corrígeme si me equivoco, pero no creo que la semántica sea cambiando en ese caso).

pub siempre ha significado "esto se exporta fuera de la caja"; esto no es un cambio, es lo que ya es. El hecho de que tantos asuman lo contrario es la razón por la cual el nivel de visibilidad pub(crate) se está impulsando.

pub siempre ha significado "esto se exporta fuera de la caja"

Creo que este entendimiento también puede causar cierta confusión, porque no es el panorama completo. pub realmente significa "No me importa quién fuera de este módulo acceda a este elemento/campo/método". Para ser exportado desde la caja, aún requiere que una ruta al elemento también tenga los mismos modificadores pub .

Este detalle es bastante habitual en muchos idiomas. También es por eso que no estoy interesado en la pelusa unreachable_pub , ya que eso es parte de lo que está impulsando tanto este problema. Si tengo un tipo que nunca se exporta en el nivel superior, molestarme porque marqué sus métodos pub simplemente se siente como ruido.

@rpjohnst ¿Es realmente lo que siempre significó? ¿No fue la cadena de "visible desde super " desde la parte superior de la caja lo que hizo que un elemento se exportara y no calificara el elemento de hoja como pub ?

No, esa no es toda la historia, y la aclaración de @seanmonstar sugiere el resto. La mayor excepción son las reexportaciones: puede pub use algo cuyos módulos principales son privados. Un ejemplo más extraño es algo como esto , donde se le permite usar un elemento pub en una interfaz pública, incluso si sus módulos principales son privados.

Y yendo en la otra dirección, pub(crate) y las visibilidades menores no se pueden pasar por alto de la misma manera: no se puede pub use algo que aún no es pub , incluso si el pub use no es visible desde fuera de la caja.

Por lo tanto, la visibilidad propia de un elemento no se trata directamente de su visibilidad en super , sino de su "límite superior" de visibilidad en cualquier lugar .

Oooh ok, gracias por la aclaración! Tenía en mente un modelo mucho más ingenuo. Tiene más sentido con respecto a los comentarios anteriores sobre "el significado actual de pub".

Hablamos brevemente hoy en la reunión de @rust-lang/lang:

  • Muchos de nosotros nos sentimos positivos al respecto, pero persisten dudas sobre la elección de la palabra clave y si puede crear confusión cuando se combina con rutas de crate::foo::bar
  • Sin embargo, vale la pena señalar que tenemos que decidir qué tipo de forma de resolver struct Foo ( crate :: foo :: Bar ) : ¿es este un campo privado de tipo (crate::foo::Bar) o es un campo crate ? de tipo ::foo::Bar ?

    • Sinceramente, no estoy seguro de lo que analizamos como hoy.

Respuesta: lo analizamos como un camino (patio de recreo ).

Esto me parece... probablemente correcto, porque creo que las rutas ::foo::bar serán cada vez más raras.

Muchos de nosotros nos sentimos positivos al respecto, pero persisten dudas sobre la elección de la palabra clave y si puede crear confusión cuando se combina con crate::foo::bar paths.

@nikomatsakis , ¿hay notas de la reunión o un resumen para que nos pongamos al día? Dentro de este hilo, no he visto discutida al menos una de mis preocupaciones[0] ni mucha discusión sobre las contrapropuestas. Tal vez [0] y algunos de los otros fueron discutidos en varios hilos internos, pero eso es mucho para profundizar.

[0] creando una sintaxis de visibilidad paralela que empuja a pub(...) a la oscuridad con la sensación de que deberíamos eliminar o adoptar pub(...)

@epage

@nikomatsakis , ¿hay notas de la reunión o un resumen para que nos pongamos al día?

No lo siento; No lo discutimos por mucho tiempo (unos minutos como máximo) y no escribimos ninguna nota de reunión al respecto.

@eddyb aludió brevemente a my como un modificador de visibilidad más corto y ergonómico.

Creo que dije mine pero my es aún más corto, ¡precioso!
(Para que conste, estaba medio bromeando en la reunión)

EDITAR : si my es local de caja, ¿podemos reemplazar pub con our ? p.ej:

our struct Foo(my FooImpl);

(Para que conste, estaba medio bromeando en la reunión)
si my es local de caja, ¿podemos reemplazar pub con our ?

Perl: hacer bromas una realidad.
https://perldoc.perl.org/functions/my.html
https://perldoc.perl.org/functions/our.html

my está bien (y ha salido antes), lo que pasa es que no está más claro que local , internal , o lo que sea, con respecto a qué (o en su caso, cuyo ), que es todo el problema.

La situación incómoda en la que nos encontramos es que queremos tener tres niveles de privacidad: "completamente público", "completamente privado" y "algún punto intermedio" (es decir, a nivel de caja), y debido a las limitaciones de compatibilidad con versiones anteriores, estamos atascados con el primero de estos siendo necesariamente pub , siendo el segundo el predeterminado implícito, y teniendo que pensar en algo nuevo para el tercero. Y el inglés no tiene muchas palabras que denoten "ni completamente global, ni completamente local, sino en algún punto intermedio" con precisión.

Y la palabra clave crate es la que satisface esto, porque dice justo en el nombre cuál es el alcance real: es la caja. Pero (antes de que empieces a decir "¡Lo sabía !"), el precio de esto es que ya no es evidente que se trata de un modificador de visibilidad . "Pub" es la abreviatura de "público", eso, uno puede intuirlo. Pero ningún otro idioma tiene el concepto de "caja" (con ese nombre); para tener alguna esperanza de encontrarle sentido a crate struct , primero hay que aprender sobre esto. 1 Nos obliga a hacer un nuevo retiro del "presupuesto de extrañeza lingüística", y las opiniones pueden diferir sobre si el balance sigue siendo positivo.

Mientras tanto pub(crate) resuelve ambos problemas: te dice que es un modificador de visibilidad y te dice cuál es el alcance, pero a cambio es largo e incómodo.

Así que esa es básicamente la forma de la situación.

1 (Alguien de arriba describió una interacción que decía, "preguntaron qué significaba crate , les dije que era un modificador de visibilidad y eso fue todo". La situación problemática, y posiblemente más común, es cuando no tienes un Rustacean sentado a tu lado).

FWIW, estaría totalmente de acuerdo con our o my para artículos locales.
our es incluso una palabra clave de tres letras y se alinea muy bien con pub ~y con Perl~.
¿El problema es que suenan demasiado informales (¿para hablantes nativos de inglés?)?

¿Cómo se siente la gente acerca de intern ? Es un carácter más largo que crate , pero aparte de eso, creo que será más intuitivo que crate para las personas nuevas en Rust y tiene una buena simetría con la palabra clave extern .

En mi opinión our y my tienen la misma debilidad que local y internal : no tienen muy claro su alcance. local en particular es bastante confuso, ya que el alcance sería radicalmente diferente de las variables locales donde local significa privado del alcance adjunto, que para un elemento sería el módulo, no la caja. Encuentro internal un poco inespecífico. ¿Interno a qué? ¿El módulo? ¿El tipo? ¿La caja? Puede ser obvio para aquellos que provienen de idiomas donde se usa, pero no necesariamente lo será para otros. our y my son aún más vagos. En contraste crate es muy claro sobre el alcance.

Con respecto a pub(extern) , en realidad tengo una pregunta. ¿Tiene algún sentido tener extern "C" fn foo() {} sin los pub al frente? Porque si no, podríamos reutilizar extern fn foo() {} para nuestras funciones regulares, no "C" abi Rust también. Estaba pensando que podríamos unificar eso y no mantener la sintaxis externa especial para las FFI. Eso significaría que extern ahora se reduce a pub(extern) , pub permanece igual que hoy pero acepta una cadena ABI opcional cuando el elemento la admite, y una pelusa para pub elementos que se exportan sin pub(extern) o extern .

extern fn foo() {
    println!("Just called a Rust function from Rust!");
}

#[no_mangle]
extern "C" fn foo_from_c() {
    println!("Just called a Rust function from C!");
}

No he visto eso mencionado en los hilos que he leído, ¡así que disculpas si esto se ha discutido antes!

¿Tiene algún sentido tener extern "C" fn foo() {} , sin el pub al frente?

Sí, a veces solo desea usar foo como puntero de función, por ejemplo. Y, de hecho, la sintaxis extern fn foo() {} no se puede reutilizar para esto de todos modos porque extern sin "C" por defecto es C ABI, y esto es considerado idiomático al menos por algunos.

Aquí hay una sugerencia que surgió hace mucho tiempo: ¿tal vez podamos darle otra oportunidad ahora que se han cristalizado algunos aspectos del nuevo sistema de módulos?

// Public to the world.
pub struct Foo;

// Private to the crate.
priv struct Foo;

// Basically not visible at all (only inside the module).
struct Foo;

Creo que esto tiene sentido si uno piensa en:

  • "público" como "público para el mundo"
  • "privado" como "privado a la caja"
  • "sin modificador de visibilidad" como "básicamente no visible en absoluto"

Algunas personas tuvieron una reacción instintiva al pensar que priv no es el más restrictivo, pero quiero señalar dos puntos al respecto:

  1. En Rust, los módulos se usan para organizar cosas en espacios de nombres, mientras que las cajas se usan para definir interfaces. Entonces, si una caja es una "unidad de API", entonces tiene sentido que los modificadores de visibilidad hablen principalmente de cajas.

  2. Creo que Java cometió un error de private que significa "privado para la clase" y ningún modificador de visibilidad que significa "visible dentro del paquete". Para mí, tiene más sentido que ningún modificador (es decir, el predeterminado) sea el más restrictivo.

@stjepang Yo diría que en la mayoría de las demás circunstancias, "privado" tendrá una connotación más restrictiva que un estado no modificado. El espectro privado-predeterminado-público en un sentido general es análogo al protegido-disponible-anunciado.

Un club privado es más exclusivo que un club.
Un acto privado implica que se hizo algún esfuerzo para esconderse de la vista general.
Un pensamiento privado debería ser un concepto redundante dado el fracaso de la evolución para dotarnos de telepatía, pero la mayoría de la gente reconoce que significa un pensamiento destinado a no ser compartido.

Como estudiante de idiomas sin experiencia, también sugeriría que una palabra clave adicional es una carga cognitiva menor que una sola palabra clave con múltiples significados dependientes del contexto. Ver Costello, L y Abbot, B "Who's on first", 1938.

Siento que my y our tendrían connotaciones que no queremos, dejando de lado la dificultad de reservarlas como palabras clave. Son una broma divertida, pero no creo que debamos ir por ese camino.

Sinceramente, siento que la gente aprendería lo que significa la visibilidad crate . Creo que el mayor problema proviene del código que se vuelve difícil de leer o ambiguo de analizar:

crate struct S(crate crate::Foo);

crate struct S(crate ::Foo);

Personalmente, no los veo como sensacionales, pero definitivamente son preocupaciones legítimas aquí.

Hay un paralelo de pub(path) en el lenguaje Scala, que es private[path] , que actúa más o menos igual. Se lee de manera ligeramente diferente, diciendo "este elemento es privado, solo permite que las personas dentro de $path lo vean". Pero hacer que algo sea privado en Scala requiere una anotación, ya que el valor predeterminado es público, que no es el caso en Rust.

Se me ocurre que el concepto de C++ de friend s también es similar a pub(path) , como otro punto de precedente.

En definitiva, los problemas son:

  1. la palabra clave crate se usa para importar rutas relativas y como modificador de visibilidad,
  2. la palabra clave crate evita una sintaxis de modificador de visibilidad unificada como pub(...) ,
  3. a algunos no les gusta la sintaxis pub(crate) (demasiado larga, parece una llamada de función).

Después de 5 minutos de pensar muy profundamente, se me ocurrió lo siguiente... :P

Sintaxis especial para los modificadores de visibilidad

_(usando @ como ejemplo)_

<strong i="18">@pub</strong> use crate::Foo;

<strong i="19">@crate</strong> struct Bar;

Personalmente, lo encuentro bastante feo y no me gustaría escribir @crate o pub(crate) .

Modificadores de visibilidad distintos Palabras clave

Dado que ya existen los pub y extern desnudos, creo que la palabra clave crate encaja bastante bien (no es sorprendente cuando se trata de idiomas con los habituales public , protected , private palabras clave).

crate struct Foo;

crate fn path() -> PathBuf { ... }

Pero como dije, eso no funciona bien con el prefijo de importación crate y empiezo a sentir que entendimos esto al revés. Siento que el problema real radica en los cambios de claridad de la ruta, por ejemplo, sin resaltado de sintaxis:

use crate::utils;

parece que crate no tiene ningún significado especial.

Con gran inspiración de la sintaxis de las macros declarativas, en lugar de encontrar algún tipo de sintaxis unificada para los modificadores de visibilidad, preferiría tener lo siguiente:

use std::io;
use std::path::Path;

use log::info;

use $crate::utils;

crate fn hello() -> io::Result<()> {
    utils::rm_rf(Path::new("/"))?;
    info!("Goodbye, World!");
}

( self , super y crate anclas especiales para importar rutas necesitarían un prefijo, por ejemplo, $crate , lo que deja bastante claro que son especiales y parecen variables)

Ejemplo enrevesado:

crate struct Foo(crate crate::Bar);

se convierte en:

crate struct Foo(crate $crate::Bar);

Parece que hay un problema de seguimiento duplicado: https://github.com/rust-lang/rust/issues/45388.
Cerrando aquél a favor de éste.

¿Hay alguna razón por la cual la implementación de rustc está probando esta característica? Cada instancia de crate fn podría cambiarse a pub(crate) fn y dejar de depender de una característica inestable AFAICT.

No veo una buena razón por la que haríamos eso. Tanto Clippy como rustc usan funciones inestables todo el tiempo y deberían hacerlo porque nos permite probarlas más extensamente tanto en términos de detección de errores en la implementación como porque podemos tener una idea de cómo se usan.

En este caso, el uso de crate como modificador de visibilidad en Clippy y en rustc muestra, en mi opinión, que se lee mejor que pub(crate) y que la mayoría de los problemas a los que se hace referencia en este problema de seguimiento no son -Problemas en la práctica. Creo que https://github.com/rust-lang/rust/issues/53120#issuecomment -413466129, https://github.com/rust-lang/rust/issues/53120#issuecomment -414392549 y https:/ /github.com/rust-lang/rust/issues/53120#issuecomment -413498376 también sugiere que crate como modificador de visibilidad también funciona bien en el exterior.

Como funciona bien en la práctica, dado que muchos de nosotros en el equipo de idiomas nos sentimos positivos al respecto , y debido a que fue aceptado por RFC , creo que deberíamos considerar estabilizar crate como un modificador de visibilidad después de considerar cómo debemos analizar struct Foo ( crate :: foo :: Bar ) ( actualmente como ruta, y probablemente así sea ).

¡FWIW, utilizo esta función en cargo-n64 y ha sido muy agradable!

Uso crate en rustc todo el tiempo porque es corto y no tiene paréntesis como pub(crate) .
Aunque todavía no me gusta cómo se lee.
Tampoco tiene 3 letras, por lo que el formato cambia junto con pub <-> crate cambios.
Todavía me gusta our sin ironía.

@petrochenkov Según tengo entendido, lo que escribió es que prefiere crate a pub(crate) pero también le gustaría algo mejor que crate . ¿Es esa una evaluación precisa?

FWIW, sigo pensando que intern es una buena opción.

  • sin paréntesis
  • Más corto que pub(crate) (aunque un carácter más largo que crate )
  • Lee mejor (IMO) que crate (que se usa para otras cosas como rutas, por ejemplo, crate::foo::bar )
  • Tiene buena simetría con extern existentes
  • Familiar, ya que otros idiomas usan algo similar ( internal ). Kotlin, C#, etc.

Dicho esto, también estoy de acuerdo en que pub(crate) debería ser reemplazado por algo .

bueno, está resuelto entonces: tres letras están bien, y "intern" está bien, así que... int . ;)

¿Podríamos tener una pelusa para el caso de crate ::T (con un espacio)?

@Centril Algunos de nosotros estábamos discutiendo el camino a seguir en #rocket. Según su comentario reciente, ¿existe la posibilidad de un FCP propuesto en el futuro cercano?

@jhpratt Tenía la intención de escribir un artículo y finalmente proponerlo, pero he estado ocupado con otras cosas. Intentaré encontrar algo de tiempo en un futuro próximo.

Entonces, solo estaba examinando problemas, buscando algo sobre macros, y encontré este.

Ahora que tenemos pub(crate) en estable durante mucho tiempo, me pregunto, ¿no debería cerrarse este problema?

Curiosamente, esto surgió en una reunión reciente del equipo de lang , donde se discutió esto como un posible problema que nos gustaría revivir.

Hablando personalmente, definitivamente extraño poder escribir crate fn y crate foo: T en los campos y ese tipo de cosas. No es una gran diferencia sintáctica con pub(crate) pero creo que hace que el código sea mucho más legible, especialmente en estructuras que tienen muchos campos públicos. También creo que contribuye a un "modelo de privacidad" razonablemente útil y simplificado:

  • estructuras, los campos son locales a un módulo (razonamiento muy limitado)
  • o se usan en algún lugar dentro de la caja actual ( crate , tienen que ripgrep alrededor)
  • o son públicos para el mundo ( pub )

Desde mi punto de vista, existe cierta intersección entre esta palabra clave y los cambios previstos en https://github.com/rust-lang/rust/issues/48054 , y preferiría asegurarme de que los adoptemos juntos. Olvidé los detalles, pero recuerdo que hubo errores que uno obtendría al intentar poner en práctica el modelo anterior.

Creo que el primer paso hacia esto sería que alguien intente escribir un informe que documente la historia y se asegure de que hayamos resaltado todas las inquietudes que se plantearon.

Una preocupación específica que sí recuerdo es la ambigüedad sintáctica de

struct Foo(crate ::x)

Hoy en día, esto se acepta y crate ::x se analiza como la ruta crate::x , pero plausiblemente el usuario pretendía que crate sirviera como modificador de visibilidad con ::x como ruta .

Me inclinaría por volver a introducir el modificador crate y mantener el análisis del caso anterior tal como está hoy. Desde Rust 2018, las rutas ::foo han quedado obsoletas en gran medida ; todavía existen y pueden ser útiles en ciertos contextos específicos, como macros, pero la mayor parte del término ahora fomentamos rutas absolutas que se ven como crate_name::b , donde crate_name podría ser la palabra clave crate o el nombre de alguna otra caja. Por lo tanto, es bastante probable que crate::x (ignorando los espacios en blanco) en realidad fuera una ruta y, por lo tanto, el análisis actual sea correcto.

Si queremos abordar la posible confusión del usuario, creo que una pelusa sensible a los espacios en blanco es una idea razonablemente buena. En otras palabras, struct Foo(crate ::x) advertiría, pero struct Foo(crate::x) no, aunque ambos son aceptados y equivalentes.

Personalmente, prefiero más la sintaxis unificada y el analizador simple lookahead(1); Además, una caja es una caja, y existe crates.io , y todo eso no tiene nada que ver con la visibilidad _directamente_, solo en el contexto de pub(_) .

Pero bueno, ¿qué sé yo? Es solo otro punto de vista. Ustedes, sin duda, tienen más experiencia y una opinión más valiosa.

@nikomatsakis Tiene curiosidad por saber si tiene alguna idea sobre intern para este caso de uso (¿o está reservando una nueva palabra clave fuera del alcance en este momento?).

Después de un par de años, mi sensación sigue siendo la misma: optimizar la legibilidad . Encuentro que leo código mucho más de lo que escribo . Entonces, mi opinión es que me queda más claro leer pub(scope) , que puede ser pub , pub(crate) , pub(super) , pub(in proto::h1) .


Sin embargo, no creo que realmente estemos agregando nada nuevo a la conversación con estas opiniones, estoy seguro de que lo hemos dicho todo en comentarios anteriores. ¿Debe basarse la decisión en algo nuevo? O dicho de otra manera, ¿cómo decidimos que ahora la decisión de adoptar esta sintaxis debería ser sí cuando fue no o posponerla hace un par de años?

También creo que contribuye a un "modelo de privacidad" razonablemente útil y simplificado:

  • estructuras, los campos son locales a un módulo (razonamiento muy limitado)
  • o se usan en algún lugar dentro de la caja actual ( crate , tienen que ripgrep alrededor)
  • o son públicos para el mundo ( pub )

No alcanzo a comprender el beneficio de esta simplificación y cómo vale la pena la pérdida de poder expresivo. Por lo que vale, a menudo hago públicos los elementos en sus módulos principales (para que los módulos hermanos puedan usarlos), pero no en la caja completa. Público al módulo de los abuelos menos, pero todavía de vez en cuando.

Siento que desaprobar pub(super) sería una pérdida significativa.


Por otra parte, no me entusiasma usar el sustantivo crate como calificador que modifica un elemento que puede existir de forma independiente. A modo de comparación: pub (lic), unsafe y const (ant) son adjetivos. Los sustantivos que ya se utilizan como palabras clave en las definiciones de elementos no son calificadores sino que indican la naturaleza de ese elemento: función, rasgo, módulo, …

Las cajas ya son un concepto que tratamos, pero en esta propuesta una definición de artículo que comienza con crate no define una nueva caja.

Un poco de información nueva:

rust-analyzer proporciona completaciones y ayudas para agregar pub(crate) , lo que (subjetivamente) hace que sea mucho menos molesto escribir, con tres pulsaciones de teclas.

Estoy de acuerdo en que se está agregando poca información nueva aquí. Creo que un buen próximo paso, si queremos defender la propuesta, sería volver atrás, resumir las inquietudes pendientes y presentarlo ante el equipo de lang para tratar de llegar a una decisión final. Ciertamente preferiría aceptar o rechazar esta propuesta, estoy cansado de tenerla en el limbo.

Después de revisar rápidamente la totalidad de este problema, creo que el comentario reciente de @nikomatsakis resume las cosas bastante bien. Aparte de unas pocas personas seleccionadas que todavía admiten cosas como intern , crate parece ser lo más lógico (y fue aceptado en RFC 2126 ). El único problema verdaderamente pendiente es cómo analizar fn foo(crate ::bar) .

Una pelusa sensible a los espacios en blanco de advertencia por defecto parece el lugar más lógico para comenzar. crate ::bar actualmente se analiza como una ruta, y tendría que permanecer así tanto en Rust 2015 como en 2018. Sin embargo, imagino que sería un candidato para un cambio importante en una edición.

El caso crate ::bar tiene importancia en la práctica y ya se comporta de manera consistente con el resto del lenguaje. Siempre ha sido la pista falsa de la discusión, por favor no centre la atención en eso.

Ciertamente preferiría aceptar o rechazar esta propuesta, estoy cansado de tenerla en el limbo.

Creo que votaría por el rechazo.
He estado usando constantemente crate en lugar de pub(crate) en rustc y, a pesar de ser más corto, parece estar fuera de lugar la mayor parte del tiempo, especialmente en campos o importaciones, y eligiendo entre crate y pub(crate) se siente como elegir entre dos males sin estar seguro de cuál es el menor.

Si. Lo que es más importante, es lo que @SimonSapin mencionó que crate bar hecho no define una nueva caja, a pesar de que se lee como si lo hiciera.

@petrochenkov ¿No crees que una pelusa tiene sentido? Personalmente, si veo crate ::bar sin ver esta discusión, espero que se comporte como pub(crate) ::bar . Creo que permitir espacios en blanco en las rutas _en absoluto_ es confuso.

@jhpratt Sería difícil negar los espacios en blanco entre los segmentos de la ruta, debido a la naturaleza de cómo funcionan los analizadores con tokens. También rompería una cantidad increíble de herramientas como quote!, syn y muchas otras.

Creo que apoyaría cerrar esto también. He visto suficiente confusión expresada sobre el significado de esta construcción que no creo que la ganancia de brevedad valga la pérdida potencial de legibilidad.

Esto puede encajar mejor en el problema de seguimiento "más grande" (pero cerrado) #44660, pero también está directamente relacionado con los modificadores de visibilidad y no se ajusta a los otros subtemas de #44660:

En algún momento recuerdo que alguien sugirió que pub(path) ahora podría ser legal, reemplazando el formulario pub(in path) y subsumiendo pub(crate) y pub(super) . Esa parece ser una buena simplificación de pub(...) , aunque en una dirección diferente a crate , que también podríamos considerar.

Editar: en realidad no estoy seguro de que esto funcione ... struct S(pub(path) Type) es ambiguo (para el análisis LL-esque) con cosas como struct S(pub (Type,)) .

Así que he estado dando este pensamiento en los últimos meses. Creo que he llegado a la posición de "cerrar". Creo que el resumen de mi posición es el siguiente:

  • La idea de "tres niveles de visibilidad" (módulo, caja, mundo) es relativamente simple, lo cual es atractivo, pero se pierde en casos comunes del mundo real. pub(super) , en particular, encuentro que es bastante común en la práctica, aunque es raro que requiera más de un nivel (es decir, pub(crate::foo) ). Por ejemplo, a menudo quiero tener módulos que tengan submódulos, y usar la visibilidad de cajas para esos detalles no logra comunicar el nivel de privacidad deseado.
  • El modelo de "local para alguna parte de la caja, o público para el mundo" también es conceptualmente simple y elegante, y cubre todos esos casos de uso.
  • pub(crate) fn , aunque significativamente menos conciso que solo crate fn , no es tan malo. Es lindo que pub(crate) se extienda a pub(crate::foo) , que cubre el otro caso de uso que a veces obtengo (es decir, módulos "grandes" dentro de una caja), pero eso es tan detallado que sospecho que rara vez lo hará. ser utilizado, y muy probablemente esos módulos grandes estarían mejor factorizados en subcajas de todos modos...
  • Creo que los mayores obstáculos ergonómicos en torno a los "niveles mixtos de privacidad" provinieron de pelusas y errores relacionados con nuestro intento de garantizar que (p. ej.) todos los tipos que aparecían en un pub(x) fn tuvieran la privacidad adecuada. Modificamos esas reglas y siento que ya no he estado enfrentando esas molestias, y si surgen más molestias de este tipo, creo que también podemos abordarlas.

    • Por ejemplo, es posible escribir pub en los campos para que signifique "tan público como la estructura misma", y creo que funciona bien.

Y, por supuesto, el hecho de que no agregue crate fn ahora no significa que no podamos agregarlo más adelante. En particular, creo que el modelo de "tres niveles de privacidad" funcionaría mejor si tuviéramos alguna forma de hacer "cajas en línea livianas" dentro de otra caja. es decir, si en lugar de tener un submódulo dentro de la caja, pudiera declarar una caja privada con todo lo que implica (más notablemente, probablemente, una relación similar a DAG con otras cosas). No estoy seguro de si las cajas en línea livianas realmente funcionarían, pero podrían cubrir y reemplazar muchos de los casos de uso similares a pub(super) . Si alguna vez explorara eso, entonces consideraría reabrir la discusión alrededor crate fn , ya que podría volverse significativamente más útil/común.

En resumen, estaría a favor de eliminar el nivel de visibilidad crate del compilador y eliminar la puerta de funciones.

Solo quería comprobar cuándo podría estabilizarse esta función y estoy sorprendido y decepcionado de que haya planes para eliminarla. Lo he estado usando todos los días desde poco después de que se agregó y casi no me molesta ninguno de los problemas discutidos anteriormente. Todavía no he escrito nada parecido a crate ::path , por ejemplo, y probablemente nunca lo haré ya que nunca toco la sintaxis ::path .

Hay margen de mejora, seguro. La palabra clave podría elegirse mejor, pub(super) sigue siendo un inconveniente, y es una molestia recibir advertencias de código inactivo por todas partes cuando uso la visibilidad a nivel de caja para los métodos auxiliares. Sin embargo, como usuario, preferiría que esta función se dejara (función limitada) hasta que se encuentre una mejor solución. La sintaxis pub(crate) es una especie de monstruosidad y desalienta un poco la división de módulos grandes en otros más pequeños y más ajustados.

creo que los mayores obstáculos ergonómicos en torno a los "niveles mixtos de privacidad" provinieron de pelusas y errores relacionados con nuestro intento de garantizar que (p. ej.) todos los tipos que aparecían en un pub(x) fn tuvieran la privacidad adecuada.

¿Significa esto que tampoco habilitamos la pelusa de "publicación inalcanzable" ( mod private { pub fn f() {} } )?

Heh, he tenido dudas mientras leía varios códigos rustc y veo crate en uso, e imagino que esos casos eran todos pub(crate) ... probablemente valdría la pena hacerlo la transición de forma experimental solo para ver cómo me hace sentir la diferencia. Recuerdo sentirme triste por la tiza cuando la cambiamos de noche a establo, aunque creo que ahora que me acostumbré no me ha molestado tanto.

@matklad Espero que no, creo que la pelusa también es bastante importante. Para ser honesto, no estoy del todo seguro de por qué no me he encontrado con ningún tipo de errores y molestias del tipo que solía tener. ¡Tal vez no he estado escribiendo suficiente código Rust últimamente! Definitivamente recuerdo que solía tener estos molestos ciclos en los que parecía que no podía satisfacer al compilador excepto haciendo muchas más cosas pub de las que quería.

¿Qué hay de mantener pub(crate) y también agregar un alias pubc ? Esto se lee bastante similar, no rompe ningún código actual y elimina la necesidad de escribir paréntesis (lo que lo hace un poco más rápido).
Esto también permitiría pubs para visibilidad en el padre.

En resumen, estaría a favor de eliminar el nivel de visibilidad crate del compilador y eliminar la puerta de funciones.

Considero que pub(crate) es un poco molesto y ruidoso cuando estoy leyendo código. Sería muy bueno tener el modificador de visibilidad crate en su lugar.

Y, por supuesto, el hecho de que no agregar crate fn ahora no significa que no podamos agregarlo más tarde. En particular, creo que el modelo de "tres niveles de privacidad" funcionaría mejor si tuviéramos alguna forma de hacer "cajas en línea livianas" dentro de otra caja. es decir, si en lugar de tener un submódulo dentro de la caja, pudiera declarar una _caja_ privada con todo lo que eso implica (sobre todo, probablemente, una relación similar a DAG con otras cosas). No estoy seguro de si las cajas en línea livianas realmente funcionarían, pero podrían cubrir y reemplazar muchos de los casos de uso similares a pub(super) . Si alguna vez explorara eso, entonces consideraría reabrir la discusión sobre crate fn , ya que podría volverse significativamente más útil/común.

¡Definitivamente me gustarían estas cajas "ligeras" que mencionas! Sería mucho mejor que ir inmediatamente a los espacios de trabajo, que son un poco pesados.

¿Fue útil esta página
0 / 5 - 0 calificaciones