Rust: (Modules) Problème de suivi pour `crate` en tant que modificateur de visibilité

Créé le 6 août 2018  ·  91Commentaires  ·  Source: rust-lang/rust

Il s'agit d'un sous-problème de suivi pour la RFC "Clarifier et rationaliser les chemins et la visibilité" (rust-lang/rfcs#2126)
traitant de la question de crate comme modificateur de visibilité.

Questions non résolues :

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

Commentaire le plus utile

Personnellement, je suis d'accord pour écrire pub(crate) , l'intention semble très explicite.
L'exemple donné par @johnthagen est vraiment pénible à voir (en utilisant 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; semble particulièrement déroutant, vous devez absolument réfléchir un peu à ce qui se passe là-bas.

Tous les 91 commentaires

Commentaires sur crate comme modificateur de visibilité :

Ambiguïté d'analyse

Non naturel / Confusion / Pas d'amélioration

Une bonne idée

pub(extern) la place

Garage à vélo

Un avant-goût

Fil dédié

Personnellement, je suis très favorable à crate comme modificateur de visibilité et je partage ici le commentaire de @stepancheg . Je pense que nous devrions encourager des visibilités plus petites et plus strictes et c'est exactement ce que fait crate .

Personnellement, je suis d'accord pour écrire pub(crate) , l'intention semble très explicite.
L'exemple donné par @johnthagen est vraiment pénible à voir (en utilisant 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; semble particulièrement déroutant, vous devez absolument réfléchir un peu à ce qui se passe là-bas.

Certains de ces exemples sont très C- static -esque- intuitivement liés mais vraiment étonnamment distincts.

L'exemple dû à @johnthagen ne me lit pas mal. En fait, ça se lit naturellement et j'aime bien la symétrie. C'est beau d'une certaine manière.

Si la lisibilité de :

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

devient un problème; alors un IDE/éditeur qui comprend la syntaxe de Rust peut mettre en évidence les jetons crate dans les différentes positions avec des couleurs différentes. Cela devrait bien éclaircir la différence je pense.

crate en tant que modificateur de visibilité est définitivement bizarre : il utilise un mot-clé très spécifique à la rouille pour une chose qui n'est pas spécifique à la rouille. Kotlin & C# utilisent internal pour cela.

Personnellement, je voudrais réutiliser pub pour crate-visible et opter pour une syntaxe plus criarde pour le monde visible, comme pub* ou pub! .

Cela a déjà été évoqué, mais je pense que les problèmes fondamentaux que je vois sont les suivants :

  1. crate est un substantif . Je pense que pub(crate) est long et étrange, donc je soutiens pleinement son remplacement par quelque chose , mais il y avait l'adjectif public qui lui était associé, donc grammaticalement, il coulait mieux.
  2. crate est maintenant utilisé comme point d'ancrage pour les importations "cette caisse", ce qui signifie quelque chose de différent de "partout où cela est défini, il est également exporté visiblement depuis cette caisse"
// 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,
}

Par rapport à un exemple, en utilisant @matklad 's internal 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,
}

Je ne dis pas que internal est le bon mot clé (Rust aime les abréviations très courtes, et int est malheureusement plein de confusion C/C++/Java), mais je pense personnellement que le deuxième exemple est tout de suite plus lisible.

Je pense aussi que le mot-clé de visibilité crate sera déroutant pour les personnes venant à Rust depuis d'autres langues. Si même beaucoup d'entre nous sont suffisamment impliqués dans Rust pour commenter ces fils de discussion, je dois imaginer que cela fera également trébucher les nouveaux venus sur Rust.

La syntaxe légèrement plus longue de pub(crate) n'est peut-être pas si grave si elle ne devenait pas un avertissement/erreur d'avoir des éléments pub qui ne sont pas accessibles en dehors de la caisse. Personnellement, je souhaite que si j'avais un pub(crate) struct Foo { ... } , que le compilateur puisse se rendre compte que tous les pub fn s dans un impl Foo ne sont clairement pas accessibles, et ne me dérangent pas à ce sujet.

Je trouve que c'est juste un travail occupé actuellement dans Rust 2015 si jamais je marque un type de pub struct Foo à pub(crate) struct Foo , comment le compilateur crie alors à tous les endroits que d'autres pub fn s existent en utilisant soudainement le type pub(crate) , lorsque le problème n'est pas réel, car l'autre type est également pub(crate) .

Je trouve également l'idée de @matklad de réaffecter pub en tant que crate-public et d'utiliser export ou quelque chose pour des exportations visibles dans le monde entier. Mais c'est peut-être un écart trop important pour une édition ?

Réaffecter pub en tant que crate-public et ajouter une nouvelle visibilité pour world-public était la proposition avant la version actuelle. Une telle modification de la sémantique existante était considérée comme trop drastique même pour une édition, c'est pourquoi pub conserve désormais sa signification actuelle.

Ce qui a été moins discuté et considéré, je pense, était la réaffectation pub uniquement via une peluche. Peut-être pourrions-nous changer la charpie de "avertir sur pub qui n'est pas accessible à l'extérieur de la caisse" à "avertir sur pub qui est accessible à l'extérieur de la caisse", et ajouter un pub(extern) purement facultatif pub(extern) / export mot-clé. C'est-à-dire, ne changez aucune sémantique, ajoutez simplement une syntaxe lint-silence.

Je soupçonne que ce serait moins perturbateur, sur la base de l'hypothèse qu'il y a moins d'objets publics mondiaux que d'objets publics de caisse. Cela préserverait également la signification intuitive (bien que subtilement incorrecte) de pub comme "exporter depuis le module actuel" plutôt que de confronter tout le monde au véritable comportement de la visibilité.

Rust aime les abréviations très courtes, et int est malheureusement plein de confusion C/C++/Java

FWIW, bien qu'il n'enregistre que deux caractères, si nous voulions abréger internal , la "bonne" abréviation serait probablement, par analogie avec extern al, être intern . Dommage que ce soit aussi un nom avec une signification commune et différente. Tant pis.

@glaebhoerl intern est une bonne option à considérer ! ❤️

La symétrie avec extern est vraiment agréable, et l'OMI réduirait considérablement la confusion potentielle avec la forme nominale de intern .

C'est court (seulement 1 caractère de plus que crate ) et n'entre pas en conflit avec use crate:: .

L'exemple mis à jour ressemblerait à :

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,
}

Je l'ai déjà mentionné, mais je ne sais pas quel est le problème avec les noms utilisés comme adjectifs ?

Pour récapituler : il existe de nombreux noms qui peuvent être utilisés comme adjectifs, par exemple. un chat domestique, une souris d'ordinateur, un bureau d'ordinateur, etc. Une recherche Google pour les _noms anglais utilisés comme adjectifs_ semble indiquer qu'il n'y a rien de mal en soi, bien que tous les noms ne fonctionnent pas comme des adjectifs.

Essayons:

_crate mod hello;_ Un module de caisse nommé hello, ça va.
_crate fn world() {}_ Une fonction de caisse nommée world, ça va.
_crate struct Foo;_ Une structure de caisse nommée Foo, se sent bien.
_crate enum Bar {}_ Un enum de caisse nommé Bar, se sent bien.
_crate trait Baz {}_ Un trait de caisse nommé Baz, ça va.

_crate use self::local::Foo;_ Ack, celui-ci ne marche pas, un crate use ? Vous pouvez le lire comme un élément utilisable dans la caisse nommé Foo. Cela casse le schéma.

Il peut également être gênant lorsqu'il est utilisé devant des membres de structure et encore plus en combinaison avec crate comme racine d'un chemin.

Bien que crate ne soit pas parfait, je ne suis pas convaincu que « être un nom » soit un facteur décisif.

Le problème c'est que c'est très rare. Je ne connais aucun langage de programmation qui utilise des noms comme modificateur de type.

@Centril

devient un problème; alors un IDE/éditeur qui comprend la syntaxe de Rust peut mettre en évidence les jetons de caisse dans les différentes positions avec des couleurs différentes. Cela devrait bien éclaircir la différence je pense.

Personnellement, bien que je trouve les fonctionnalités des différents éditeurs agréables, je ne pense pas que nous devrions concevoir le langage en supposant un éditeur suffisamment avancé. J'avais l'impression que C # était conçu de cette façon et c'était un facteur majeur dans ma frustration avec ce langage.

@epage Je pense que crate en tant que modificateur de visibilité est une bonne idée, quelle que soit la mise en surbrillance; Je suggère simplement que la mise en évidence est une atténuation supplémentaire . En particulier, il devrait être assez trivial pour tout éditeur de mettre en évidence crate:: différemment de crate field car le premier est toujours crate + :: ce qui est facile à vérifier pour dans tous les cas sauf crate ::foo::bar (mais ce sera assez rare..).

En tant que personne IDE, je pense qu'une telle mise en évidence ajouterait une quantité importante de bruit pour une très petite quantité d'informations, ce qui serait négatif. IMO (ceci est très personnel, mais informé à la fois par l'utilisation et l'implémentation d'IDE puissants) la mise en évidence fonctionne mieux lorsqu'elle transmet des informations sémantiques non locales (cette utilisation fait-elle référence à une variable qui a été déclarée avec mut ) et de souligne les aspects locaux de "boilerplaty" du code (donc tous les mots-clés doivent avoir exactement le même style).

Il me semble que dom (c'est-à-dire domestique) est un candidat potentiel.

Il a trois lettres (agréable pour l'alignement, facile à retenir), ce n'est pas un nom et - à part 'Document Object Model' - je ne pense pas qu'il y ait d'ambiguïté particulière qui lui soit attachée.

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

Est-ce que quelqu'un a des idées à ce sujet?

Un angle à ce sujet que j'ai vu mentionné mais que je n'ai pas trouvé dans le résumé (merci de l'avoir fait d'ailleurs !) Est de savoir comment un raccourci s'intègre à la syntaxe pub() existante.

Si pub et <something> (par exemple crate ) ont une signification particulière, cela réduit encore la visibilité, et par extension la familiarité, de pub(<something>) . Quelle que soit la solution choisie, je pense qu'elle devrait soutenir ou remplacer la machinerie existante plutôt que d'en être une autre.

Par exemple, si nous utilisons crate ou remplacement :

  • Doit-on étendre crate pour prendre en charge les restrictions de portée (par exemple, crate(<something>) ) ?
  • Devrions-nous déprécier pub() donc pub n'a qu'une seule signification ?

Compte tenu de cela et de ma compréhension de l'objectif (clarifier l'API publique de l'API interne), m'a amené à recréer l'idée de @vitiral de pub(extern) .

  • S'intègre dans les machines existantes
  • imo améliore les machines existantes en faisant pub un raccourci de pub(<something>) plutôt que d'être un cas particulier
  • Si l'API publique est nettement plus petite que l'API privée, nous avons pondéré la syntaxe de la bonne manière.
  • Mais cela pourrait confondre les personnes venant d'autres langues où public signifie qu'il pourrait être dans votre API publique.

RE Impact sur l'encapsulation

L'encapsulation est l'un des avantages du système pub existant. Le chemin le plus simple consiste à n'exposer l'API qu'à un niveau supérieur. Cela facilite la création de choses publiques pour certaines parties d'une caisse mais privées pour l'ensemble.

Bien qu'il y ait toujours pub(super) , avoir un raccourci pour pub(crate) poussera les gens à l'utiliser davantage, les encourageant à ne pas encapsuler leurs API.

Je soupçonne que ce n'est pas un problème à cause de la culture des petites caisses.

Mais en considérant cela, cela me donne une autre itération sur mon commentaire ci-dessus sur pub(extern)

  • pub devrait être un raccourci pour pub(super)
  • pub(extern) est requis pour votre API publique.

J'ai déjà évoqué la préoccupation des personnes en transition depuis d'autres langues. Cela correspond mieux à eux.

  • Correspond plus étroitement au fonctionnement public dans différentes langues
  • Certaines langues ont tendance à avoir un mécanisme distinct pour l'API publique, cela leur est donc explicable.

imo c'est le meilleur de tous les mondes. Alors déchirez-le et aidez-moi à comprendre pourquoi pas :)

Je déteste toujours la syntaxe pub(foo) . De manière hyperbolique, il semble qu'il ne puisse pas décider s'il s'agit d'un appel de fonction ou d'un mashup de plusieurs mots-clés. Nous n'utilisons pas let(mut) ou for(in) alors quel est le problème avec celui-ci ?

@parasyte pub<foo> pour la victoire ! Après tout, n'est-ce pas un _type de visibilité_ ?

pub<crate> ou pub(crate) se sentent vraiment mieux.

Quelques réflexions de quelqu'un qui a changé de camp :

Au début, j'étais très opposé à crate et je pensais "c'est en train de ruiner le joli pub ".

Je l'ai ensuite essayé côte à côte dans certains de mes projets et je l'ai laissé pénétrer.

Franchement, après quelques jours, je ne supportais plus de regarder pub(X) , c'était maladroit en comparaison et plus difficile à lire.

Au début, je craignais qu'il y ait une ambiguïté (visuelle); mais pour moi, c'est le contraire qui s'est produit : si je vois crate maintenant, je sais que c'est, eh bien, "des trucs de caisse". Qu'il s'agisse d'importer des modules ou de déclarer la visibilité. Qu'est-ce qui est exactement dans l'écrasante majorité des cas très clair à partir du contexte (un peu comme l'ambiguïté en anglais).

Je peux voir qu'il peut y avoir encore une ambiguïté "plus dure" (visuelle) résiduelle dans certains cas, mais je ne voudrais pas échanger cela contre ce qui ressemble maintenant à une énorme victoire de lisibilité quantitative (comme dans : "les lignes de code source qui nécessitent moins de tokenisation visuelle / d'effort par rapport aux lignes de code source qui sont devenues plus ambiguës").

Sous cet angle, crate - intern (ou toute autre asymétrie) donnerait également l'impression d'un pas en arrière.

Cela dit, je ne connais pas l'ambiguïté d'analyse. Si je devais en choisir une, je préférerais de loin avoir une bonne histoire autour de " crate signifie des trucs de caisse" qu'une bonne histoire autour de " crate ::foo::bar ça marche".

Mes deux cents sont que :

  • J'ai beaucoup utilisé crate mod , crate struct , crate fn , ... et je le trouve extrêmement utile.
  • Je me fiche de savoir comment il est nommé ( crate , pub(crate) , ...) tant qu'il n'est pas trop long car je l'utilise souvent.

Si cela ne tenait qu'à moi, j'utiliserais vis comme mot-clé et le type de visibilité comme modificateur, par exemple vis(pub) , vis(crate) , etc. car cela rend plus sens pour moi.

Étant donné que nous sommes déjà coincés avec pub comme "spécificateur de visibilité", j'aime en fait crate . Le pub(crate) se lit pour moi comme public pour ce module, privé pour la caisse - je trouve bizarre d'utiliser à la fois public et privé ici.

Introduire de nouveaux mots-clés et des mots-clés contextuels, etc. n'en vaut pas la peine à mon avis. Enseigner qu'il y a deux modifications de visibilité pub et crate , et que l'un signifie public, et l'autre signifie privé pour la caisse, cela a du sens pour moi, mais peut-être que je viens de m'y habituer crate déjà au cours des deux dernières semaines.

À ceux qui suggèrent qu'un mot-clé déjà utilisé (c'est-à-dire : crate ) confond les significations, je dirais que le contexte est plus important que le mot lui-même. Le cerveau analyse tout avec le contexte (comment le compilateur analyse cela est une autre affaire): cela explique pourquoi nous ne confondons pas la signification sémantique de for en for x in y et impl X for Y .

De même, l'introduction crate comme qualificatif de visibilité ne créerait probablement pas de confusion car sa signification, dans le contexte d'un qualificatif de membre ou de fonction, est évidente lorsqu'elle est fournie avec ce contexte supplémentaire. Par exemple, crate fn my_func(); ne se lit pas comme "c'est une caisse", mais comme "c'est une fonction visible dans la caisse".

Cela dit, le fait qu'il s'agisse d'un nom est incohérent. Je serais favorable à la création d'un nouveau mot-clé qualificatif de visibilité pour résoudre ce problème.

En fait, s'il y a quelque chose qui confondra définitivement les utilisateurs, c'est la syntaxe pub(crate) qui ressemble intuitivement à un appel de fonction et n'a pas d'autre équivalent syntaxique ailleurs dans le langage. Pour moi, cela ressemble à un vilain hack.

En tant que personne qui a soulevé des inquiétudes concernant l'utilisation crate en remplacement de pub(crate) et après avoir lu le dernier message de @aturon :

Prise en charge de la caisse en tant que modificateur de visibilité (suivi ici 138. Compte tenu des commentaires jusqu'à présent, il est peu probable que cette fonctionnalité soit stabilisée pour Rust 2018 .

Je veux juste m'assurer que je suis clair que je suis personnellement entièrement en faveur du remplacement de pub(crate) par quelque chose (comme je pense que la majorité l'est).

Par ordre de préférence, avec ce qui, selon moi, serait le plus facile à saisir, en particulier pour ceux qui découvrent ou ne connaissent pas Rust :

  1. intern (ou un autre nouveau mot-clé similaire)
  2. crate
  3. pub(crate)

Si l'équipe de base a l'impression que intern ou quelque chose de similaire ne serait finalement jamais accepté, alors je serais derrière crate car je pense toujours que c'est une grande amélioration par rapport à pub(crate) , pour les raisons que @Centril et d'autres ont articulées.

Je ne m'opposerais donc pas à cela si l'équipe de base, beaucoup plus expérimentée, estime que c'est la meilleure voie à suivre. C'est bien de pouvoir simplement fournir des commentaires et exprimer des idées à prendre en considération. 👍 Rouille !

@ralfbiedert

Au début, je craignais qu'il y ait une ambiguïté (visuelle); mais pour moi, c'est le contraire qui s'est produit : si je vois une caisse maintenant, je sais que c'est, eh bien, "des trucs de caisse". Qu'il s'agisse d'importer des modules ou de déclarer la visibilité. Qu'est-ce qui est exactement dans l'écrasante majorité des cas très clair à partir du contexte (un peu comme l'ambiguïté en anglais).

@zesterer

À ceux qui suggèrent qu'un mot-clé déjà utilisé (c.-à-d. : caisse) confond les significations, je dirais que le contexte est plus important que le mot lui-même. Le cerveau analyse tout avec le contexte (la façon dont le compilateur analyse cela est une autre affaire) : cela explique pourquoi nous ne confondons pas la signification sémantique de for in for x in y et impl X for Y.

Je ne veux pas vous appeler personnellement, mais servir d'exemples de personnes en faveur du changement après l'avoir utilisé.

Bien que je trouve cela bizarre, ma plus grande préoccupation concerne les non-rustacés.

  • Comment cela pourrait-il avoir un impact sur l'opinion de quelqu'un dans l'évaluation de la rouille ? Une bizarrerie de syntaxe ne devrait pas suffire à les dissuader, mais si vous l'empilez avec des durées de vie et toute autre chose "étrange", cela pourrait décourager les gens
  • Quel impact cela a-t-il sur les personnes qui apprennent Rust ?
  • Quel impact cela a-t-il sur les personnes qui ne connaissent pas Rust mais qui ont besoin de le modifier ?

J'aimerais bien que nous puissions faire des études d'utilisabilité à ce sujet pour mieux connaître l'impact de ces préoccupations.

@epage , tout à fait d'accord, les parties de Rust destinées à l'utilisateur doivent être testées UX. Cependant, je pense que c'est ce qui se passe en ce moment, et nous sommes en train de discuter des résultats.

Pour ajouter à cela, quelques observations anecdotiques de notre société :

Je suis le "défenseur de la rouille" dans notre département, travaillant avec 3 autres personnes. Tous ont une solide expérience en C #, mais sont relativement nouveaux sur Rust. L'autre jour, j'ai migré notre projet de recherche vers Rust 2018, avec les " crate -trucs".

Lorsque nous avons parcouru le code, les conversations se sont déroulées à peu près comme ceci :

"Voici donc quelques autres modifications que j'ai apportées ; nouveau système d'importation ; modificateurs."

"Qu'est-ce que ça fait ?" (pointant vers use crate::object et crate x: object )

"Importer depuis cette caisse." et "Modificateur de visibilité."

« Ah, d'accord. Y a-t-il autre chose qui a changé ? »

Fin de la conversation.

Nous avons sûrement discuté un peu plus des nouvelles fonctionnalités et de la question de savoir si nous devrions adopter certains modèles. mais "l'aspect pédagogique" de ces deux items se résumait à quelques mots et n'a plus été évoqué depuis (à ma connaissance).

Si j'entends autre chose la prochaine fois que nous parlerons, je mettrai à jour ce commentaire.

@ralfbiedert Merci d'avoir partagé ça !

@epage , tout à fait d'accord, les parties de Rust destinées à l'utilisateur doivent être testées UX. Cependant, je pense que c'est ce qui se passe en ce moment, et nous sommes en train de discuter des résultats.

Bien que j'apprécie ces anecdotes UX, en particulier pour le côté apprentissage, je ne pense pas que je qualifierais le processus de ce problème de test UX. Mon commentaire fait référence à un processus plus formel qui peut aider à approfondir la compréhension, à éliminer les préjugés, etc.

Voici quelques réflexions venant d'un novice de Rust. Tout d'abord, je tiens à dire que quelque chose qui semble vraiment sain et agréable avec ce langage est l'approche "immuable par défaut, privée par défaut".

Maintenant, pub est bien parce que c'est simple et attendu dans les langues modernes. Je pense que devoir désapprendre cela dans le contexte de Rust et saupoudrer un autre mot-clé partout à la place est un peu maladroit. Sémantiquement, il semble juste que cela signifie "c'est un bouton qui apparaît sur la boîte", la boîte étant le module : visibilité "d'un niveau vers le haut".

Donc, pour moi, utiliser crate ou un autre mot-clé de cette nature au lieu de pub me démange : si être public n'est pas la valeur par défaut, être exporté hors de la caisse devrait être encore plus spécial . C'est-à-dire que l'API de la caisse doit être désignée d'une manière spéciale.

Donc, je suis entièrement d'accord avec @epage , pub devrait rester le même et un pub(extern) quelconque être introduit. Les mots-clés entre parenthèses semblent vraiment poilus, alors peut-être mériteraient-ils un mot-clé dédié. Le mot-clé crate fonctionnerait dans ce sens, je peux le voir signifier "ceci est un membre de caisse exporté". Ou export en fait, je ne sais pas. Peut-être que tout ce que je veux dire est un hangar à vélos, et tout cela revient à "les mots-clés ne sont pas corrects". Mais pub est si courant qu'il ne semble pas spécial, il ne devrait donc pas représenter quelque chose de vraiment spécial (l'API crate-exported).

J'ai regardé une conférence à RustConf ce week-end qui utilisait beaucoup de pub(crate) dans ses exemples de code, et cela m'a vraiment fait souhaiter le bon vieux crate . Je suis toujours très pro du plan initial.

@steveklabnik

J'ai regardé une conférence à RustConf ce week-end qui utilisait beaucoup de pub (caisse) dans ses échantillons de code, et cela m'a vraiment fait souhaiter une vieille caisse ordinaire. Je suis toujours très pro du plan initial.

Le contexte de ce commentaire provient-il principalement de RustConf ou prend-il en compte ce fil et présuppose-t-il un désaccord avec celui-ci ? Plus tôt, j'ai fourni une solution alternative, non pas pour pub(crate) mais pour les exigences entraînant l'un des changements de pub et j'espère que cela satisfera les besoins des gens.

Voir

@superseed

Donc, je suis entièrement d'accord avec @epage , la pub devrait rester la même et une pub (externe) d'une sorte ou d'une autre devrait être introduite. Les mots-clés entre parenthèses semblent vraiment poilus, alors peut-être mériteraient-ils un mot-clé dédié. crate mot-clé fonctionnerait dans ce sens, je peux le voir signifier "ceci est un membre de caisse exporté". Ou exporter en fait, je ne sais pas. Peut-être que tout ce que je veux dire est un hangar à vélos, et tout cela revient à "les mots-clés ne sont pas corrects". Mais le pub est si courant qu'il ne semble pas spécial, il ne devrait donc pas représenter quelque chose de vraiment spécial (l'API crate-exported).

RE "Les mots clés entre parenthèses sont vraiment poilus"

Alors que personnellement, je pensais qu'ils étaient bien quand je les ai découverts (bien mieux que tout ou rien friend ), ma plus grande préoccupation est que nous ne créons pas de syntaxe parallèle mais que nous acceptons ce que nous avons ou trouvons une solution alternative.

D'autre part...

RE Ou export en fait,

Je ne pense pas que l'ajout d'un export contredit mon commentaire précédent contrairement à crate . Dans ce contexte, export peut être traité comme différent de la visibilité. export impliquerait pub(crate) . Je soupçonne que cela n'aura pas beaucoup de problème dans l'enseignement.

Je peux aller dans les deux sens sur cette extension de mon idée originale.

@superseed

pub […] visibilité "d'un niveau vers le haut".
Le mot-clé crate fonctionnerait dans ce sens, je peux le voir signifier "ceci est un membre de caisse exporté".

Je pense que votre compréhension de la signification de ces deux mots clés peut être l'exact opposé de ce qui est proposé ici, à savoir que pub signifie public pour tout le monde tandis que crate signifie accessible à partir de la même caisse.

@epage

Dans le cas de pub(crate) , il offre une fonctionnalité vraiment intéressante et se lit bien, mais ressemble trop à un appel de fonction à mes yeux. c'est-à-dire que sans la mise en évidence syntaxique, je serais probablement vraiment confus, et la mise en évidence ne devrait pas être nécessaire pour comprendre la sémantique d'une langue.

@SimonSapin

En effet, et je me rends compte que c'est ainsi qu'il est censé être compris, mais crate - étant un nom - donne l'impression de déclarer soit une caisse (?) soit une propriété de la caisse. L'accent est mis sur la déclaration et non sur la qualification.

Et public / pub est un qualificatif tellement omniprésent qu'il ne me semble pas (pour moi !) que cela devrait signifier "ceci est exporté hors de la caisse". Cela signifie "ceci est visible juste en dehors du contexte dans lequel je me trouve", comme c'est le cas avec son utilisation pour qualifier la visibilité des membres struct (et corrigez-moi si je me trompe mais je ne le fais pas ' Je ne pense pas que la sémantique change dans ce cas).

Et public/pub est un qualificatif tellement omniprésent qu'il ne me semble pas (pour moi !) que cela devrait signifier "ceci est exporté hors de la caisse". Il a cette signification de "ceci est visible juste en dehors du contexte dans lequel je me trouve", comme c'est le cas avec son utilisation dans la qualification de la visibilité des membres de la structure (et corrigez-moi si je me trompe mais je ne pense pas que la sémantique soit changer dans ce cas).

pub a toujours signifié "ceci est exporté hors de la caisse" - ce n'est pas un changement, c'est déjà comme ça. Le fait que tant de personnes supposent le contraire est la raison pour laquelle le niveau de visibilité pub(crate) est poussé du tout.

pub a toujours signifié "ceci est exporté hors de la caisse"

Je pense que cette compréhension peut également causer une certaine confusion, car ce n'est pas une image complète. pub signifie vraiment "Je me fiche de qui en dehors de ce module accède à cet élément/champ/méthode". Pour être exporté depuis la caisse, il faut toujours qu'un chemin vers l'élément comporte également les mêmes modificateurs pub .

Ce détail est assez courant dans de nombreuses langues. C'est aussi pourquoi je n'aime pas les peluches unreachable_pub , car cela fait partie de ce qui pousse tellement ce problème. Si j'ai un type qui n'est jamais exporté au niveau supérieur, alors me harceler que j'ai marqué ses méthodes pub ressemble à du bruit.

@rpjohnst Est-ce vraiment ce que cela a toujours signifié ? N'était-ce pas la chaîne de "visible depuis super " du haut de la caisse qui faisait qu'un élément était exporté, et ne qualifiait pas l'élément feuille lui-même comme pub ?

Non, ce n'est pas toute l'histoire, et la clarification de @seanmonstar fait allusion au reste. La plus grande exception concerne les réexportations - vous pouvez pub use quelque chose dont les modules parents sont privés. Un exemple plus étrange est quelque chose comme ceci , où vous êtes autorisé à utiliser un élément pub dans une interface publique même si ses modules parents sont privés.

Et dans l'autre sens, pub(crate) et les visibilités moindres ne peuvent pas être contournées de la même manière - vous ne pouvez pas pub use quelque chose qui n'est pas déjà pub , même si le pub use n'est pas lui-même visible de l'extérieur de la caisse.

Ainsi, la visibilité propre d'un élément ne concerne pas directement sa visibilité à super , mais sa "limite supérieure" de visibilité n'importe où .

Oooh d'accord, merci pour la précision ! J'avais en tête un modèle beaucoup plus naïf. Cela a plus de sens concernant les commentaires précédents sur "la signification actuelle de pub".

Nous avons discuté brièvement aujourd'hui lors de la réunion @rust-lang/lang :

  • Beaucoup d'entre nous sont positifs à ce sujet, mais il subsiste des doutes quant au choix du mot-clé et s'il peut créer de la confusion lorsqu'il est combiné avec des chemins crate::foo::bar
  • Cependant, il convient de souligner que nous devons décider de quelle manière résoudre struct Foo ( crate :: foo :: Bar ) -- s'agit-il d'un champ privé de type (crate::foo::Bar) ou s'agit-il d'un champ crate de type ::foo::Bar ?

    • Je ne suis honnêtement pas sûr de ce que nous analysons comme aujourd'hui

Réponse : nous l'analysons comme un chemin ( aire de jeux).

Cela me semble .. probablement correct, car je pense que les chemins ::foo::bar deviendront de plus en plus rares.

Beaucoup d'entre nous sont positifs à ce sujet, mais il subsiste des doutes quant au choix du mot-clé et s'il peut créer de la confusion lorsqu'il est combiné avec crate::foo::bar paths

@nikomatsakis y a-t-il des notes de réunion ou un résumé à rattraper ? Dans ce fil, je n'ai pas vu discuté au moins une de mes préoccupations [0] ni beaucoup de discussions sur les contre-propositions. Peut-être que [0] et certains des autres ont été discutés dans les différents fils de discussion internes, mais c'est beaucoup à creuser.

[0] créer une syntaxe de visibilité parallèle poussant pub(...) dans l'obscurité avec le sentiment que nous devrions soit supprimer, soit adopter pub(...)

@epage

@nikomatsakis y a-t-il des notes de réunion ou un résumé à rattraper ?

Non désolé; Nous n'en avons pas discuté très longtemps (quelques minutes tout au plus) et n'avons pas écrit de notes de réunion à ce sujet.

@eddyb a brièvement fait allusion à my comme modificateur de visibilité plus court et plus ergonomique.

Je pense que j'ai dit mine mais my est encore plus court, adorable !
(Pour mémoire, je plaisantais à moitié lors de la réunion)

EDIT : si my est crate-local, pouvons-nous remplacer pub par our ? par exemple:

our struct Foo(my FooImpl);

(Pour mémoire, je plaisantais à moitié lors de la réunion)
si my est crate-local, pouvons-nous remplacer pub par our ?

Perl : faire des blagues une réalité.
https://perldoc.perl.org/functions/my.html
https://perldoc.perl.org/functions/our.html

my est sympa (et est déjà apparu), le fait est que ce n'est pas plus clair que local , internal , ou quoi que ce soit, par rapport à quoi (ou dans son cas, dont ), qui est tout le problème.

La situation embarrassante dans laquelle nous nous trouvons est que nous voulons avoir trois niveaux de confidentialité -- "complètement public", "complètement privé" et "quelque part entre les deux" (c'est-à-dire au niveau de la caisse) -- et en raison de contraintes de rétrocompatibilité, nous 're coincé avec le premier d'entre eux étant nécessairement pub , le second étant la valeur par défaut implicite et devant proposer quelque chose de nouveau pour le troisième. Et l'anglais n'a pas beaucoup de mots qui dénotent "ni complètement global, ni complètement local, mais quelque part entre les deux" avec précision.

Et le mot-clé crate est celui qui satisfait cela , car il indique directement dans le nom quelle est la portée réelle - c'est la caisse. Mais (avant que vous n'éclatiez les "je le savais !"), le prix à payer est qu'il n'est plus évident qu'il s'agit d'un modificateur de visibilité . "Pub" est l'abréviation de "public", cela, on peut le deviner. Mais aucune autre langue n'a le concept de "caisse" (avec ce nom); pour avoir le moindre espoir de donner un sens à crate struct , il faut d'abord apprendre à ce sujet. 1 Il nous oblige à effectuer un prélèvement supplémentaire sur le « budget de l'étrangeté linguistique », et les avis peuvent diverger quant à savoir si le solde est toujours positif.

Pendant ce temps, pub(crate) résout les deux problèmes -- il vous indique qu'il s'agit d'un modificateur de visibilité, et il vous indique quelle est la portée -- mais en échange, c'est long et gênant.

Voilà donc essentiellement la forme de la situation difficile.

1 (Quelqu'un ci-dessus a décrit une interaction qui disait : "ils ont demandé ce que crate voulait dire, je leur ai dit que c'était un modificateur de visibilité, et c'était la fin". La situation problématique, et peut-être la plus courante, c'est quand vous n'avez pas de Rustacé assis à côté de vous.)

FWIW, je serais tout à fait d'accord avec our ou my pour les articles locaux en caisse.
our est même un mot-clé de trois lettres et s'aligne parfaitement avec pub ~et avec Perl~.
Le problème est-il qu'ils semblent trop informels (pour les anglophones natifs ?) ?

Que pensent les gens de intern ? C'est un caractère plus long que crate , mais à part ça, je pense qu'il sera plus intuitif que crate pour les nouveaux utilisateurs de Rust et a une belle symétrie avec le mot-clé extern .

IMO our et my ont la même faiblesse que local et internal : ils ne sont pas très clairs sur leur portée. local en particulier est assez déroutant, car la portée serait radicalement différente des variables locales où local signifie privé à la portée englobante, qui pour un élément serait le module, pas la caisse. Je trouve internal un peu imprécis. Interne à quoi ? Le module ? Le type? La caisse ? C'est peut-être évident pour ceux qui viennent des langues où il est utilisé mais ça ne le sera pas forcément pour les autres. our et my sont encore plus vagues. En revanche, crate est très clair sur la portée.

Concernant pub(extern) , j'ai une question. Cela a-t-il un sens d'avoir jamais extern "C" fn foo() {} , sans le pub devant ? Parce que sinon, nous pourrions également réutiliser extern fn foo() {} pour nos fonctions régulières non "C" abi Rust. Je pensais que nous pourrions unifier cela et ne pas garder la syntaxe externe spéciale pour les FFI. Cela signifierait que extern se désucre maintenant en pub(extern) , pub reste le même qu'aujourd'hui mais accepte une chaîne ABI facultative lorsque l'élément le prend en charge, et une peluche pour pub éléments exportés sans pub(extern) ou 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!");
}

Je n'ai pas vu cela mentionné dans les fils de discussion que j'ai lus, alors excusez-moi si cela a déjà été discuté!

Cela a-t-il un sens d'avoir jamais extern "C" fn foo() {} , sans le pub devant ?

Oui - parfois, vous souhaitez uniquement utiliser foo comme pointeur de fonction, par exemple. Et en fait, la syntaxe extern fn foo() {} ne peut pas être réutilisée pour cela de toute façon car extern sans "C" est par défaut l'ABI C, et cela est considéré comme idiomatique au moins par certains.

Voici une suggestion qui est apparue il y a longtemps - peut-être pouvons-nous lui donner une autre chance maintenant que certains aspects du nouveau système de modules ont été cristallisés ?

// 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;

Je pense que cela a du sens si l'on pense à:

  • « public » comme « public au monde »
  • "privé" comme "privé à la caisse"
  • "pas de modificateur de visibilité" comme "essentiellement pas visible du tout"

Certaines personnes ont eu une réaction instinctive au fait priv n'était pas le plus restrictif, mais je tiens à souligner deux points à ce sujet :

  1. Dans Rust, les modules sont utilisés pour organiser les choses sous des espaces de noms, tandis que les caisses sont utilisées pour définir les interfaces. Donc, si une caisse est une "unité d'API", il est logique que les modificateurs de visibilité parlent principalement de caisses.

  2. Je pense que Java a fait une erreur de private signifiant "privé à la classe" et aucun modificateur de visibilité signifiant "visible à l'intérieur du package". Pour moi, il est plus logique qu'aucun modificateur (c'est-à-dire la valeur par défaut) soit le plus restrictif.

@stjepang Je dirais que dans la plupart des autres circonstances, "privé" aura une connotation plus restrictive qu'un état non modifié. Le spectre privé-public par défaut dans un sens général est analogue au spectre protégé-disponible-annoncé.

Un club privé est plus exclusif qu'un club.
Un acte privé implique qu'un certain effort a été fait pour se cacher de la vue générale.
Une pensée privée devrait être un concept redondant étant donné l'échec de l'évolution à nous doter de télépathie, mais la plupart des gens reconnaissent qu'elle signifie une pensée destinée à ne pas être partagée.

En tant qu'apprenant de langue inexpérimenté, je suggérerais également qu'un mot-clé supplémentaire est moins un fardeau cognitif qu'un seul mot-clé avec plusieurs significations dépendant du contexte. Voir Costello, L et Abbot, B "Qui est le premier", 1938.

Je pense que my et our auraient des connotations que nous ne voulons pas, en laissant de côté la difficulté de les réserver comme mots-clés. Ils font une plaisanterie amusante, mais je ne pense pas que nous devrions emprunter cette voie.

Honnêtement, j'ai l'impression que les gens apprendraient ce que signifie la visibilité crate . Je pense que le plus gros problème vient du code qui devient difficile à lire ou ambigu à analyser :

crate struct S(crate crate::Foo);

crate struct S(crate ::Foo);

Personnellement, je ne les considère pas comme des obstacles, mais ce sont certainement des préoccupations légitimes ici.

Il y a un parallèle de pub(path) dans le langage Scala, qui est private[path] , qui agit à peu près de la même manière. Il se lit légèrement différemment, en disant "cet élément est privé, permettant uniquement aux personnes dans $path de le voir". Mais rendre quelque chose de privé dans Scala nécessite une annotation, car la valeur par défaut est publique, ce qui n'est pas le cas dans Rust.

Il me semble que le concept C++ de friend s est également similaire à pub(path) , comme autre point de précédent.

Au final, les enjeux sont :

  1. le mot-clé crate est utilisé à la fois pour les importations de chemins relatifs et comme modificateur de visibilité,
  2. le mot-clé crate empêche une syntaxe de modificateur de visibilité unifiée comme pub(...) ,
  3. certains n'aiment pas la syntaxe pub(crate) (trop longue, ressemble à un appel de fonction).

Après 5 minutes de réflexion très approfondie, j'ai trouvé ce qui suit... :P

Syntaxe spéciale pour les modificateurs de visibilité

_(en utilisant @ comme exemple)_

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

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

Personnellement, je trouve cela assez moche et je ne voudrais pas taper @crate ou pub(crate) .

Mots-clés distincts des modificateurs de visibilité

Puisqu'il y a déjà les seuls pub et extern , je pense que le mot-clé crate s'intègre assez bien (ce qui n'est pas surprenant lorsqu'il vient de langues avec l'habituel public , protected , private mots-clés).

crate struct Foo;

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

Mais comme je l'ai dit, cela ne fonctionne pas bien avec le préfixe d'importation crate et je commence à avoir l'impression que nous avons inversé cela. Je pense que le vrai problème réside dans les changements de clarté du chemin, par exemple, sans coloration syntaxique:

use crate::utils;

ressemble à crate n'a pas de signification particulière.

Avec une grande inspiration de la syntaxe des macros déclaratives, au lieu de trouver une sorte de syntaxe unifiée pour les modificateurs de visibilité, je préférerais avoir ce qui suit :

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 et crate les ancres spéciales pour les importations de chemins auraient besoin d'un préfixe, par exemple, $crate , ce qui indique clairement qu'elles sont spéciales et ressemblent à des variables)

Exemple compliqué :

crate struct Foo(crate crate::Bar);

devient:

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

Il semble qu'il y ait un problème de suivi en double : https://github.com/rust-lang/rust/issues/45388.
Clôturant celui-là au profit de celui-ci.

Y a-t-il une raison pour laquelle l'implémentation de rustc utilise cette fonctionnalité ? Chaque instance de crate fn pourrait être remplacée par pub(crate) fn et cesser de s'appuyer sur une fonctionnalité AFAICT instable.

Je ne vois pas de bonne raison pour laquelle nous ferions cela. Clippy et rustc utilisent tous les deux des fonctionnalités instables et ils le devraient car cela nous permet de les tester plus en profondeur à la fois en termes de détection de bogues dans l'implémentation et parce que nous pouvons avoir une idée de la façon dont il est de les utiliser.

Dans ce cas, l'utilisation de crate comme modificateur de visibilité dans Clippy et dans rustc montre à mon avis qu'il se lit mieux que pub(crate) et que la plupart des problèmes référencés dans ce problème de suivi ne sont pas -problèmes en pratique. Je pense https://github.com/rust-lang/rust/issues/53120#issuecomment -413466129, https://github.com/rust-lang/rust/issues/53120#issuecomment -414392549, et https:/ /github.com/rust-lang/rust/issues/53120#issuecomment -413498376 suggèrent également que crate en tant que modificateur de visibilité fonctionne également bien à l'extérieur.

Comme cela fonctionne bien dans la pratique, puisque beaucoup d'entre nous dans l'équipe linguistique en sont satisfaits et parce que c'était accepté par RFC , je pense que nous devrions envisager de stabiliser crate comme modificateur de visibilité après avoir réfléchi à la façon dont nous devrions analyser struct Foo ( crate :: foo :: Bar ) ( actuellement en tant que chemin, et c'est probablement vrai ).

FWIW, j'utilise cette fonctionnalité dans cargo-n64 et ça a été très sympa !

J'utilise tout le temps crate dans rustc parce que c'est court et qu'il n'y a pas de parenthèses comme pub(crate) .
Je n'aime toujours pas la façon dont il se lit cependant.
Il n'a pas non plus 3 lettres, donc le formatage change avec pub <-> crate change.
J'aime toujours our sans ironie.

@petrochenkov Si j'ai bien compris ce que vous avez écrit, vous préférez crate à pub(crate) , mais vous aimeriez aussi quelque chose de mieux que crate . Est-ce une évaluation précise?

FWIW, je pense toujours que intern est une bonne option.

  • Pas de parenthèses
  • Plus court que pub(crate) (mais un caractère plus long que crate )
  • Lit mieux (IMO) que crate (qui est utilisé pour d'autres choses comme les chemins, par exemple crate::foo::bar )
  • A une belle symétrie avec les extern existants
  • Familier, car d'autres langues utilisent quelque chose de similaire ( internal ). Kotlin, C#, etc.

Cela étant dit, je suis également d'accord que pub(crate) devrait être remplacé par quelque chose .

eh bien c'est réglé alors-- trois lettres c'est bien, et "interne" c'est bien, donc... int . ;)

Pourrions-nous s'il vous plaît avoir une peluche pour le boîtier crate ::T (avec un espace) ?

@Centril Quelques-uns d'entre nous discutaient juste de la voie à suivre sur #rocket. Sur la base de votre commentaire récent, existe-t-il une possibilité d'un FCP proposé dans un avenir proche ?

@jhpratt J'avais l'intention de faire un article et éventuellement de le proposer, mais j'ai été occupé par d'autres choses. Je vais essayer de trouver du temps dans un futur proche.

Donc, je parcourais juste les problèmes, cherchais quelque chose sur les macros, et j'ai trouvé celui-ci.

Maintenant que nous avons pub(crate) stable depuis longtemps déjà, je me demande si ce problème ne devrait pas être clos ?

Fait intéressant, cela vient d'être soulevé lors d'une récente réunion de l'équipe lang , où nous en avons discuté comme d'un problème possible que nous aimerions relancer.

Personnellement, je manque vraiment de pouvoir écrire crate fn et crate foo: T sur les champs et ce genre de choses. Ce n'est pas un gros diff syntaxique de pub(crate) mais je trouve que cela rend le code beaucoup plus lisible, en particulier dans les structures qui ont beaucoup de champs publics. Je trouve également que cela contribue à un "modèle de confidentialité" raisonnablement utile et simplifié --

  • structs, les champs sont soit locaux à un module (raisonnement très étroit)
  • ou ils sont utilisés quelque part dans la caisse actuelle ( crate , il faut ripgrep autour)
  • ou ils sont publics au monde ( pub )

À mon avis, il y a donc une certaine intersection entre ce mot-clé et les changements envisagés dans https://github.com/rust-lang/rust/issues/48054 , et je préférerais m'assurer que nous les adoptons ensemble. J'oublie les détails mais je me souviens qu'il y avait des erreurs que l'on obtenait en essayant de mettre en pratique le modèle ci-dessus.

Je pense que la première étape dans ce sens serait que quelqu'un essaie de rédiger un article documentant l'histoire et s'assurant que nous avons mis en évidence toutes les préoccupations qui ont été soulevées.

Une préoccupation particulière dont je me souviens est l'ambiguïté syntaxique de

struct Foo(crate ::x)

Aujourd'hui, ceci est accepté et crate ::x analyse comme chemin crate::x , mais il est plausible que l'utilisateur veuille dire que crate sert de modificateur de visibilité avec ::x comme chemin .

Je serais enclin à réintroduire le modificateur crate et à conserver l'analyse du cas ci-dessus tel qu'il est aujourd'hui. Depuis Rust 2018, les chemins ::foo ont été largement obsolètes - ils existent toujours et peuvent être utiles dans certains contextes spécifiques, comme les macros, mais la plupart du temps, nous encourageons maintenant les chemins absolus qui ressemblent à crate_name::b , où crate_name peut être soit le mot-clé crate soit le nom d'une autre caisse. Il est donc assez probable que crate::x (en ignorant les espaces) était en fait un chemin et que l'analyse actuelle est donc correcte.

Si nous voulons remédier à la confusion potentielle des utilisateurs, je pense qu'une peluche sensible aux espaces blancs est une assez bonne idée. En d'autres termes, struct Foo(crate ::x) avertirait, mais struct Foo(crate::x) ne le ferait pas, bien que les deux soient acceptés et équivalents.

Personnellement, je préfère davantage la syntaxe unifiée et l'analyseur simple lookahead(1) ; De plus, une caisse est une caisse, et il y a crates.io là-bas, et tout ça n'a rien à voir avec la visibilité _directement_ — seulement dans le contexte de pub(_) .

Mais bon, qu'est-ce que je sais ? C'est juste un autre point de vue. Vous avez sans aucun doute plus d'expérience et une opinion plus précieuse.

@nikomatsakis Curieux de savoir si vous avez des idées sur intern pour ce cas d'utilisation (ou réservez-vous un nouveau mot clé hors de portée à ce stade ?).

Après quelques années, mon sentiment est toujours le même : optimiser la lisibilité . Je trouve que je lis beaucoup plus de code que je n'en écris . Et donc, mon opinion est qu'il est plus clair pour moi de lire pub(scope) , qui peut être pub , pub(crate) , pub(super) , pub(in proto::h1) .


Cependant, je ne pense pas que nous ajoutions vraiment quelque chose de nouveau à la conversation avec ces opinions, je suis sûr que nous avons tout dit dans les commentaires précédents. La décision devrait-elle être fondée sur quelque chose de nouveau? Ou dit d'une autre manière, comment décidons-nous que maintenant la décision d'adopter cette syntaxe devrait être oui alors qu'elle était non ou reportée il y a quelques années ?

Je trouve également que cela contribue à un "modèle de confidentialité" raisonnablement utile et simplifié --

  • structs, les champs sont soit locaux à un module (raisonnement très étroit)
  • ou ils sont utilisés quelque part dans la caisse actuelle ( crate , il faut ripgrep autour)
  • ou ils sont publics au monde entier ( pub )

Je n'arrive pas à comprendre le bénéfice de cette simplification et comment cela vaut la perte de puissance expressive. Pour ce que ça vaut, je rends souvent les éléments publics à leurs modules parents (afin que les modules frères puissent les utiliser) mais pas à l'ensemble de la caisse. Public vers le module grand-parent moins, mais toujours occasionnellement.

Je pense que déprécier pub(super) serait une perte importante.


Séparément, je ne suis pas ravi d'utiliser le nom crate comme qualificatif qui modifie un élément qui peut exister indépendamment. À titre de comparaison : pub(lic), unsafe et const(ant) sont des adjectifs. Les noms déjà utilisés comme mots-clés dans les définitions d'items ne sont pas des qualificatifs mais indiquent la nature de cet item : fonction, trait, module, …

Les caisses sont déjà un concept que nous traitons, mais dans cette proposition, une définition d'article qui commence par crate ne définit pas une nouvelle caisse.

Une petite nouvelle info :

rust-analyzer fournit des complétions et des aides pour ajouter pub(crate) , ce qui (subjectivement) le rend beaucoup moins ennuyeux à taper, à trois frappes.

Je suis d'accord que peu de nouvelles informations sont ajoutées ici. Je pense qu'une bonne prochaine étape, si nous voulons défendre la proposition, serait de revenir en arrière, de résumer les préoccupations en suspens et de la soumettre à l'équipe lang pour essayer de parvenir à une décision finale. Je préférerais certainement accepter ou rejeter cette proposition, j'en ai assez de la laisser dans les limbes.

En examinant rapidement l'intégralité de ce problème, je pense que le récent commentaire de @nikomatsakis résume assez bien les choses. Mis à part quelques personnes sélectionnées qui supportent encore des choses comme intern , crate semble être la plus logique (et a été acceptée dans la RFC 2126 ). Le seul problème vraiment en suspens est de savoir comment analyser fn foo(crate ::bar) .

Un lint sensible aux espaces blancs averti par défaut semble l'endroit le plus logique pour commencer. crate ::bar est actuellement analysé comme un chemin, et devrait le rester dans Rust 2015 et 2018. J'imagine que ce serait un candidat pour un changement de rupture dans une édition, cependant.

Le cas crate ::bar n'a aucune importance dans la pratique et se comporte déjà de manière cohérente avec le reste du langage. Cela a toujours été le faux-fuyant de la discussion, s'il vous plaît ne focalisez pas votre attention dessus.

Je préférerais certainement accepter ou rejeter cette proposition, j'en ai assez de la laisser dans les limbes.

Je pense que je voterais pour le refus.
J'ai toujours utilisé crate au lieu de pub(crate) dans rustc et bien qu'il soit plus court, il semble toujours déplacé la plupart du temps, en particulier sur les champs ou les importations, et je choisis entre crate et pub(crate) donne l'impression de choisir entre deux maux sans savoir lequel est le moindre.

Ouais. Ce qui est plus important, c'est ce que @SimonSapin a mentionné que crate bar ne définit en effet pas une nouvelle caisse, même si elle se lit comme si c'était le cas.

@petrochenkov Vous pensez qu'une peluche n'a pas de sens ? Personnellement, si je voyais crate ::bar sans voir cette discussion, je m'attendrais à ce qu'il se comporte comme pub(crate) ::bar . Je pense qu'autoriser les espaces blancs dans les chemins _at all_ est déroutant.

@jhpratt Il serait difficile de refuser les espaces entre les segments de chemin, en raison de la nature du fonctionnement des analyseurs avec les jetons. De plus, cela casserait une quantité insensée d'outils comme quote!, syn et bien d'autres.

Je pense que je soutiendrais la fermeture de cela aussi. J'ai vu suffisamment de confusion exprimée sur la signification de cette construction pour que je ne pense pas que le gain de brièveté vaille la perte potentielle de lisibilité.

Cela peut mieux correspondre au problème de suivi "plus large" (mais fermé) # 44660, mais il est également directement lié aux modificateurs de visibilité et ne correspond pas aux autres sous-problèmes de # 44660 :

À un moment donné, je me souviens que quelqu'un a suggéré que pub(path) pourrait désormais être légal, en remplaçant le formulaire pub(in path) et en subsumant pub(crate) et pub(super) . Cela semble être une belle simplification de pub(...) , bien que dans une direction différente de crate , que nous pourrions également envisager.

Edit : En fait, je ne suis pas sûr que cela fonctionne... struct S(pub(path) Type) est ambigu (pour l'analyse LL-esque) avec des choses comme struct S(pub (Type,)) .

J'ai donc réfléchi à cette question au cours des derniers mois. Je pense que je suis arrivé à la position "fermée". Je pense que le résumé de ma position est le suivant :

  • L'idée de "trois niveaux de visibilité" (module, caisse, monde) est relativement simple, ce qui est attrayant, mais elle passe à côté des cas courants du monde réel. pub(super) , en particulier, je trouve que c'est vraiment assez courant dans la pratique, bien qu'il soit rare d'exiger plus d'un niveau (c'est-à-dire pub(crate::foo) ). Par exemple, je veux souvent avoir des modules qui ont des sous-modules, et l'utilisation de la visibilité de la caisse pour ces détails ne parvient pas à communiquer le niveau de confidentialité souhaité.
  • Le modèle "local à une partie de la caisse, ou public au monde" est également conceptuellement simple et élégant, et il couvre tous ces cas d'utilisation.
  • pub(crate) fn , bien que nettement moins concis que simplement crate fn , n'est pas si mal. C'est mignon que pub(crate) s'étende à pub(crate::foo) , qui couvre l'autre cas d'utilisation que j'obtiens parfois (c'est-à-dire, de "gros" modules dans une caisse), mais c'est tellement verbeux que je soupçonne que ce sera rarement, voire jamais être utilisés, et il est fort probable que ces gros modules seraient de toute façon mieux pris en compte dans les sous-caisses ...
  • Je pense que les plus grands obstacles ergonomiques autour des "niveaux mixtes de confidentialité" sont venus des peluches et des erreurs liées au fait que nous essayions de nous assurer que (par exemple) tous les types qui apparaissaient dans un pub(x) fn étaient d'une confidentialité appropriée. Nous avons peaufiné ces règles et j'ai juste l'impression que je n'ai plus rencontré ces désagréments - et si d'autres désagréments de ce type surviennent, je pense que nous pouvons également les résoudre.

    • Par exemple, il est possible d'écrire pub sur les champs pour signifier "aussi public que la structure elle-même", et je pense que cela fonctionne très bien.

Et, bien sûr, le fait de ne pas ajouter crate fn maintenant ne signifie pas que nous ne pouvons pas l'ajouter plus tard. En particulier, je pense que le modèle des "trois niveaux de confidentialité" fonctionnerait mieux si nous avions un moyen de faire des "caisses légères en ligne" dans une autre caisse. c'est-à-dire si au lieu d'avoir un sous-module dans la caisse, je pouvais déclarer une caisse privée avec tout ce que cela implique (notamment, probablement, une relation de type DAG avec d'autres choses). Je ne sais pas si des caisses en ligne légères fonctionneraient réellement, mais elles pourraient couvrir et remplacer de nombreux cas d'utilisation de type pub(super) . Si jamais je devais explorer cela, alors j'envisagerais de rouvrir la discussion autour crate fn , car cela pourrait devenir beaucoup plus utile/commun.

En bref, je serais en faveur de la suppression du niveau de visibilité crate du compilateur et de la suppression de la porte de fonctionnalité.

Je voulais juste vérifier quand cette fonctionnalité pourrait être stabilisée et je suis surpris et déçu qu'il soit prévu de la supprimer. Je l'utilise au quotidien depuis peu de temps après son ajout et je ne suis guère dérangé par aucun des problèmes évoqués ci-dessus. Je n'ai toujours rien écrit qui ressemble à crate ::path , par exemple, et je ne le ferai probablement jamais puisque je ne touche jamais à la syntaxe ::path .

Il y a place à l'amélioration, bien sûr. Le mot-clé pourrait être mieux choisi, pub(super) est toujours gênant, et c'est une nuisance d'obtenir des avertissements de code mort partout lorsque j'utilise la visibilité au niveau de la caisse pour les méthodes d'assistance. En tant qu'utilisateur, cependant, je préférerais que cette fonctionnalité soit laissée (fonctionnalité fermée) jusqu'à ce qu'une meilleure solution soit trouvée. La syntaxe pub(crate) est en quelque sorte une horreur et décourage légèrement de diviser les gros modules en modules plus petits et plus serrés.

pense que les plus grands obstacles ergonomiques autour des "niveaux mixtes de confidentialité" sont venus des peluches et des erreurs liées à notre tentative de nous assurer que (par exemple) tous les types qui apparaissaient dans un pub (x) fn étaient d'une confidentialité appropriée.

Cela signifie-t-il que nous n'activons pas non plus les peluches "pub inaccessibles" ( mod private { pub fn f() {} } ) ?

Heh, j'ai eu des doutes en lisant divers codes rustc et en voyant crate en cours d'utilisation, et j'imagine que ces cas étaient tous pub(crate) ... ça vaudrait probablement la peine d'être fait la transition expérimentalement juste pour voir comment le diff me fait sentir. Je me souviens d'avoir été triste pour la craie lorsque nous l'avons déplacée de la nuit à l'écurie, même si je pense que maintenant que je m'y suis habitué, cela ne m'a pas trop dérangé.

@matklad J'espère que non, je pense que la peluche est assez importante aussi. Pour être honnête, je ne suis pas tout à fait sûr de la raison pour laquelle je n'ai rencontré aucun type d'erreurs et d'ennuis du genre que j'avais l'habitude d'avoir. Peut-être que je n'ai pas écrit assez de code Rust ces derniers temps ! Je me souviens très bien que j'avais ces cycles ennuyeux où il semblait que je ne pouvais pas satisfaire le compilateur, sauf en faisant beaucoup plus de choses pub que je ne le voulais.

Qu'en est-il de conserver pub(crate) et d'ajouter également un alias pubc ? Cela se lit assez similaire, ne casse aucun code actuel et supprime la nécessité de taper des parenthèses (ce qui le rend un peu plus rapide).
Cela permettrait également à pubs de visibilité dans le parent.

En bref, je serais en faveur de la suppression du niveau de visibilité crate du compilateur et de la suppression de la porte de fonctionnalité.

Je trouve que pub(crate) est une sorte d'horreur et de bruit lorsque je lis du code. Ce serait vraiment bien d'avoir le modificateur de visibilité crate à la place.

Et, bien sûr, le fait de ne pas ajouter crate fn maintenant ne signifie pas que nous ne pouvons pas l'ajouter plus tard. En particulier, je pense que le modèle des "trois niveaux de confidentialité" fonctionnerait mieux si nous avions un moyen de faire des "caisses légères en ligne" dans une autre caisse. c'est-à-dire, si au lieu d'avoir un sous-module dans la caisse, je pouvais déclarer un _crate_ privé avec tout ce que cela implique (notamment, probablement, une relation de type DAG avec d'autres choses). Je ne sais pas si des caisses en ligne légères fonctionneraient réellement, mais elles pourraient couvrir et remplacer de nombreux cas d'utilisation de type pub(super) . Si jamais je devais explorer cela, alors j'envisagerais de rouvrir la discussion autour crate fn , car cela pourrait devenir beaucoup plus utile/commun.

J'aimerais bien ces caisses "légères" dont tu parles ! Ce serait beaucoup plus agréable que d'aller immédiatement dans des espaces de travail, qui sont plutôt lourds.

Cette page vous a été utile?
0 / 5 - 0 notes