Rust: Problème de suivi pour la RFC 2126 : Clarifier et rationaliser les chemins et la visibilité

Créé le 17 sept. 2017  ·  120Commentaires  ·  Source: rust-lang/rust

Il s'agit d'un problème de suivi pour la RFC « Clarifier et rationaliser les chemins et la visibilité » (rust-lang/rfcs#2126).

Pas:

Questions non résolues :

  • Comment aborder la migration ? Via un repli, comme proposé, ou via des époques ? Il est probablement préférable de prendre cette décision avec plus d'expérience, par exemple après avoir un outil rustfix en main.

  • La syntaxe finale pour les chemins absolus ; il y a plus de bikeshedding à faire ici dans un contexte où nous pouvons réellement essayer les différentes options. En particulier, il y a de réels avantages à avoir à la fois des chemins crate:: et extern:: , mais idéalement, nous pourrions le faire de manière plus succincte.

B-RFC-approved C-tracking-issue E-needs-mentor T-lang WG-compiler-front

Commentaire le plus utile

Voici une autre instance que je viens de rencontrer et qui combine le mot-clé crate à la fois dans un modificateur de visibilité et dans un chemin, ce qui semble encore plus probable que l'instance crate use crate... .

Courant:

pub(crate) struct Bar {
    pub(crate) foo: ::Foo,
}

pub(crate) struct Baz(pub(crate) ::Foo);

Avec les modifications apportées à ce problème de suivi :

crate struct Bar {
    crate foo: crate::Foo,
}

crate struct Baz(crate crate::Foo);

Personnellement, je trouve que la nouvelle version est plus déroutante que la méthode actuelle.

Tous les 120 commentaires

Ce RFC a 4 fonctionnalités distinctes et pourtant nous n'avons toujours qu'un seul problème de suivi pour chacun d'eux. Pouvons-nous, s'il vous

@retep998 Comme expliqué tout au long des discussions RFC, ces fonctionnalités sont liées par des considérations de conception globale. Par exemple, fournir un mécanisme externe pour renommer les caisses est motivé en partie par l'éventuelle dépréciation de extern crate . Nous pouvons et allons contrôler différents aspects séparément (et aurons probablement des portes qui se chevauchent pour essayer différentes syntaxes), mais pour la discussion sur la conception globale et la stabilisation, il est important de garder à l'esprit la cohérence globale.

Avoir un mécanisme externe pour renommer les caisses est quelque chose qui est déjà souhaité et nécessaire depuis des années (https://github.com/rust-lang/cargo/issues/1311) et qui aurait pu se suffire à lui-même, mais à la place il est utilisé comme rien de plus qu'un pion pour soutenir l'élimination de extern crate .

Nous n'avons eu aucun problème à avoir des RFC séparés pour des fonctionnalités étroitement liées dans le passé (les RFC pour repr(align(N)) et repr(packed(N)) me viennent à l'esprit), mais maintenant nous prétendons que changer foo/mod.rs à foo.rs est-il si étroitement lié à extern:: et crate:: qu'ils doivent être dans le même RFC et utiliser le même problème de suivi ?

Juste pour vous assurer que ce point persiste, car il s'agit d'un aspect relativement subtil de la question non résolue de la syntaxe : l'utilisation de crate comme modificateur de visibilité ainsi qu'un préfixe de chemin introduit une ambiguïté d'analyse entre crate ::absolute::path et crate::relative::path . L'utilisation d'un mot-clé contextuel introduit la même ambiguïté, et il n'y a pas d'autres mots-clés réservés qui ont vraiment du sens en tant que modificateurs de visibilité.

J'aimerais donc (au moins) expérimenter en omettant le modificateur de visibilité crate et en conservant le pub(crate) existant.

Cela ne me dérangerait pas de diviser le point foo.rs / foo/mod.rs en un problème de suivi distinct, car cela semble vraiment indépendant des changements de chemin et de modificateur de visibilité.

En ce qui concerne le renommage de caisse externe ... il y a déjà une autre question pour elle? C'est assez important pour les changements de chemin, donc je pense que c'est bien de faire partie de celui-ci également .

Malgré de nombreuses discussions il y a quelques semaines concernant le choix de crate comme modificateur de visibilité (pas un préfixe de chemin), je suis déçu de voir que bien que ce choix de mot-clé ait été répertorié comme une "question non résolue" dans le RFC, il est désormais apparemment oublié. Moi-même, et plusieurs autres que j'ai notés, je trouve ce choix déroutant car ce n'est pas un adjectif/modificateur, et peut également être ambigu : crate signifie-t-il une partie de l'API publique de la caisse ? Non! Cela signifie local ou internal ou pub (lished) à la caisse (c'est pourquoi je préfère ces derniers mots-clés). Je n'exige donc pas de changement immédiat, mais au moins le reconnaisse comme une question non résolue dans ce problème de suivi, afin qu'il ne soit pas oublié lors de la stabilisation.

C'est bien que cette refonte de module ait progressé jusqu'à présent, mais en même temps, il est important que nous ne fassions pas de gaffes juste pour faire la « période d'implémentation » et finir par prendre des décisions sans consulter la majorité des utilisateurs de Rust. Et, malheureusement, je pense que les personnes impliquées dans les discussions sur Github RFC ne sont pas représentatives de l'ensemble de la base d'utilisateurs, en raison du flot d'informations/commentaires/opinions qui peuvent être décourageants. Donc, d'une manière ou d'une autre, il faut aussi s'en occuper.

On ne sait pas comment la mise en œuvre s'est terminée...

@rpjohnst @retep998 J'ai ouvert une nouvelle RFC pour discuter de foo.rs + foo/ et proposer quelques améliorations à cette RFC.

Edit : je suggère que nous ouvrions un autre RFC pour discuter de crate tant que modificateur de visibilité. Personnellement, j'aimerais voir le contraire : pub(extern) soit ajouté et requis pour tous les symboles publiés en externe. Cela ferait en sorte que pub nu soit l'équivalent de pub(crate) à l'époque suivante.

@rpjohnst

introduit une ambiguïté d'analyse entre crate ::absolute::path et crate::relative::path

Le code crate ::relative::path n'est-il pas

@ est31 Non, cela nécessite une résolution de nom pendant l'analyse, ce qui n'est certainement pas quelque chose que nous voulons faire. C'est l'une des parties les plus ennuyeuses de l'analyse C et C++, qui ont des ambiguïtés similaires autour de a * b étant une multiplication ou une déclaration, et autour de a b(c, d); étant une déclaration de variable ou un prototype de fonction.

Si jamais nous commençons à autoriser les dépendances et les modules de niveau supérieur avec le même nom, même embrouiller la résolution de noms avec l'analyse ne nous sauvera pas - crate :: some :: item pourrait être un crate -visible item de la dépendance some , ou un item privé du module de niveau supérieur some .

Pour garder cela en perspective, nous pourrions simplement résoudre arbitrairement l'ambiguïté d'une manière ou d'une autre et exiger des parenthèses pour écrire l'autre cas (probablement le cas du chemin absolu crate -visibility, qui semble le plus rare), mais c'est toujours un cas foot-gun dont nous n'avons pas besoin si nous nous en tenons à pub(crate) , qui a déjà résolu l'ambiguïté syntaxique.

L'utilisation de crate comme modificateur de visibilité ainsi qu'un préfixe de chemin introduit une ambiguïté d'analyse entre crate ::absolute::path et crate::relative::path .

Il s'agit d'un petit problème, IMO, étant donné que les deux visibilités sur les champs de structure de tuple et les chemins absolus "en ligne" sont rares.
Les chemins sont toujours analysés avidement actuellement, il est donc logique que crate :: x :: y signifie crate::x::y .
Si le sens opposé est recherché, alors pub(crate) ::x::y ou crate (::x::y) peuvent être utilisés.

@rpjohnst @petrochenkov pourriez-vous partager un exemple de code où pub ::relative::path est un code valide ? Je ne comprends pas toute l'ambiguïté parce que je pense que l'un des deux cas est invalide.

Edit : le seul endroit où cela pourrait être pertinent est à l'intérieur des macros lorsque vous recherchez un qualificatif de visibilité + un chemin. Mais c'est une toute petite casse donc acceptable IMO.

@ est31 Vous semblez avoir une mauvaise idée - il ne s'agit pas de chemins relatifs, ils ne sont jamais un problème. Il s'agit de construire l'AST avant de savoir à quoi se réfère l'un des noms. Voici un échantillon complet :

struct S(crate :: x :: y);

Étant donné que vous n'êtes pas encore autorisé à rechercher l'un de ces noms, comment convertissez-vous cette chaîne de caractères en AST ? Il y a deux réponses possible. On a un champ privé de type y défini dans le module x de la caisse courante. L'autre a un champ crate -visible d'un type différent y défini au niveau supérieur de la dépendance x . Aucune macro nécessaire.

@rpjohnst Je vois merci pour la clarification. C'est effectivement une ambiguïté.

@rpjohnst

Une solution simple consiste à le définir sans ambiguïté parse dans le modificateur de visibilité de caisse. Si vous souhaitez l'analyser en tant que structure de tuple avec un membre privé du type donné, procédez comme suit :

    struct S(:: crate :: x :: y);

(notez le préfixe :: pour indiquer la racine 'namespace')

Ceci est cohérent avec la façon dont les autres espaces de noms racine doivent être référencés dans les sous-modules (par exemple, ::std::x::y ).

Le simple fait de lever l'ambiguïté en crate -as-a-visibility serait quelque peu surprenant, je pense. Mais ce pourrait être une bonne idée de "canoniser" un peu cette solution de contournement et d'imposer que crate:: soit toujours utilisé avec un :: début (en dehors des use s bien sûr). Comme vous le soulignez, cela augmente la symétrie avec les chemins de type ::std::x::y et laisse la forme sans préfixe pour les chemins vraiment relatifs ( self:: / super:: / something_in_scope:: ).

Doit-on faire ça ? Autoriser crate::x::y dans des chemins non use rend crate peu magique, tandis que l'application de ::crate::x::y étend au même niveau que les dépendances, c'est ce que nous' essaie d'impliquer de toute façon.

@rpjohnst

imposer que crate:: est toujours utilisé avec un :: tête (en dehors des utilisations bien sûr)

Cela peut être raisonnable, au moins pour un début (rien n'empêche de relâcher cela plus tard).

Je ne suis pas fan de la syntaxe use extern::bar::foo ou use crate::bar::foo . Cela semble très bruyant. Je préférerais du sucre pour cela. Je suggère extern bar::foo pour cela.

Que diriez-vous d'ajouter une règle implicite supplémentaire ? Importez automatiquement la caisse externe dans l'espace de noms racine, créez une expression de chemin plus coïncidente. (Je ne suis pas bon en anglais, veuillez apprendre mon point de vue à partir de l'exemple suivant)

par exemple

  1. Notre structure de projet comme ceci:

src
|--lib.rs
|--foo.rs
|--foo
|----|--bar.rs

  1. vous configurez une dépendance dans Cargo.toml, comme
    [dependencies] serde = "3.0.0"

  2. nous ajoutons le mod bar dans le mod foo , et ajoutons le mod foo dans lib.rs,

  3. nous définissons une fonction finlib dans lib.rs, définissons une fonction finfoo dans foo.rs, définissons une fonction finbar dans bar.rs

Faites de la portée de la caisse externe le module de niveau supérieur dans la caisse, puis nous pouvons écrire du code comme celui-ci n'importe où.

pour un parcours complet/qualifié

::serde::Deserialize
::serde::x::y
::finlib                            // not ::crate::finlib
::foo::finfoo                   // not ::crate::foo::finfoo
::foo::bar::finbar           // not ::crate::foo::bar::finbar

chemin relatif écrit comme ceci

serde::Deserialize      // no need to write `use serde`
serde::x::y                   // no need to write `use serde`
finlib                          
foo::finfoo                  
bar::finbar       

nous recherchons d'abord serdefinlibfoo dans la portée actuelle du mod, s'il n'est pas trouvé dans le mod du souper, jusqu'à l'espace de noms racine. s'il y a un conflit de nom, nous écrivons entièrement le chemin à la place.

nous pouvons également utiliser self::bar::finbar dans foo.rs pour éviter la recherche de nom.

Je ne suis pas en mesure de trouver le fil de discussion précédent qui en a parlé, mais le compilateur fonctionnait de cette façon et cela a causé des problèmes majeurs pour la résolution de noms. IIRC @pcwalton ou @arielb1 en savent probablement plus.

La solution la plus simple à cette ambiguïté ne serait-elle pas d'utiliser un mot-clé différent pour le modificateur de visibilité crate-local (c'est-à-dire le remplacement pub(crate) ). Par exemple, local , comme suggéré plusieurs fois auparavant dans les discussions RFC précédentes. Alors struct S(local :: x :: y) est distinct de struct S(crate :: x :: y) .

Cela introduit juste une autre ambiguïté entre <visibility> <absolute path> et <relative path starting with the new keyword> , puisque le nouveau mot-clé devrait être contextuel.

@rpjohnst ah putain .. Mais n'est-ce pas un problème que les époques ont été conçues pour résoudre? Ex : dans l'époque actuelle, nous utilisons simplement pub(crate) , puis, dans l'époque suivante, introduisons un nouveau mot-clé non contextuel qui est plus « ergonomique ».

@ neon64 oui mais c'est une affirmation de la RFC selon laquelle il ne nécessite pas une nouvelle époque. Cette affirmation semble ne pas tenir.

Cela tient très bien - il n'y a actuellement aucun code qui utilise la visibilité crate ou les chemins crate:: , donc seul le nouveau code sera affecté. Tant que nous choisissons une résolution et que nous la respectons, il n'y a pas de problèmes de compatibilité.

Une chose qui m'est venue à l'esprit, avec des excuses si cela a déjà été évoqué dans l'une des discussions (je ne me souviens pas l'avoir vu dans les deux derniers):

Dans la dernière proposition, nous avons crate:: pour faire référence à "dans cette caisse" et self:: pour faire référence à "dans ce module". C'est légèrement incohérent et potentiellement moins clair qu'il ne pourrait l'être : d'une part, où self fait référence à « ceci », il n'est pas intrinsèquement évident « ce quoi », et inversement, du fait qu'il existe un self:: qui signifie " ce module", on pourrait en déduire que crate:: pourrait signifier " une autre caisse", ce qui est une confusion qui a en fait été mentionnée dans le fil.

Une solution possible serait d'éliminer progressivement self:: en faveur de mod:: . Ensuite, nous aurions crate:: pour signifier "dans la caisse englobante la plus proche", et mod:: pour signifier "dans le module enclos le plus proche", et ce serait clair et cohérent. On pourrait aussi résoudre potentiellement le problème où il est impossible de se référer à des éléments dans un fn façon qualifiée portée tout en introduisant un fn:: préfixe, pour sans surprise moyenne « dans le englobante le plus proche fn ". (Je ne me suis pas demandé s'il serait judicieux d'aller plus loin, et aussi d'avoir des choses comme trait:: ou impl:: .)

@glaebhoerl c'est une proposition intéressante. Personnellement, je pense être venu à l'idée d'introduire une nouvelle syntaxe pour les chemins absolus et de déprécier celle qui existe. Je ne sais pas à quoi devrait ressembler cette syntaxe, mais je décrirai une possibilité ci-dessous (dont je sais qu'elle a déjà été flottante).

Imaginez que nous ayons la grammaire suivante pour les chemins :

Path = AbsolutePath | RelativePath
AbsolutePath = 
    | `@` ID? 
    | `@` ID? `::` RelativePath
    | `self` :: RelativePath
    | `super` :: RelativePath
RelativePath = ID (`::` ID)*

Selon cette grammaire, on référencerait des choses d'autres caisses en commençant par @crate , par exemple :

use <strong i="13">@std</strong>::collections::HashMap;

On ferait référence à la caisse locale avec seulement @ , par exemple :

use @::something::in::my::crate;

(Et use self::something reste le même qu'aujourd'hui, pour le meilleur ou pour le pire.)

Ce qui est bien, c'est que les chemins absolus se distinguent complètement des chemins relatifs, ce qui signifie que nous avons maintenant la propriété souhaitable que l'on peut copier-coller un chemin à partir d'un use dans le code et cela fonctionne :

fn foo() {
    <strong i="24">@std</strong>::cmp::min(a, b) // OK
}

Ce n'est pas vrai aujourd'hui, ce qui me trouble définitivement de temps en temps.

Nous éliminons également l'ambiguïté d'analyse autour de crate , vous pouvez donc faire pub Foo(crate @::MyType) ou autre et cela fonctionne bien.

(En général, avoir des chemins relatifs et absolus commençant par le même :: a été une source de douleur plusieurs fois, c'est la vérité.)

Une chose que je ne sais pas, c'est si @foo est le meilleur. L'autre option que je pense fonctionne et à laquelle j'ai pensé est [] :

  • [std]::collections et [crate]::collections // []::collections semble trop bizarre.

Je ne pense vraiment pas que nous devrions introduire de nouveaux sceaux juste pour les chemins. L'application d'un :: de début dans ::crate::foo suffit pour traiter le commentaire de @glaebhoerl et pour éliminer l'ambiguïté de l'analyse. Il correspond également plus étroitement au modèle mental prévu pour crate:: - c'est un substitut pour le nom de la caisse actuelle, pas un préfixe de chemin comme self:: .

(En général, le fait que les chemins relatifs et absolus commencent par le même :: a été une source de douleur plusieurs fois, c'est la vérité.)

Je ne sais pas ce que vous entendez par là. Je ne pense pas que les chemins relatifs commencent par :: , n'est-ce pas ?

@nikomatsakis @glaebhoerl indépendamment du fait que j'aime ou non vos suggestions (en fait, je peux vivre avec les deux), pouvons-nous s'il vous plaît nous en tenir à la RFC ? Cela a fait l'objet de nombreuses discussions et je ne pense pas que rouvrir le débat aiderait qui que ce soit. Un total de 82 personnes ont commenté le fil de la dernière RFC (il y a eu pas mal de discussions auparavant), beaucoup en étant très convaincus. Je pense qu'il serait injuste pour eux de se faufiler dans un changement de dernière minute de la proposition à ce stade, sans leur donner une chance d'examiner le changement.
Surtout, je suis un peu confus car dans #44721 @nikomatsakis a fermé la discussion sur la fonctionnalité avec l'argument "parlons uniquement de l'implémentation s'il vous plaît".

La notation @ et la notation [] ont toutes deux été proposées (je suis un partisan des deux) mais elles n'ont finalement pas réussi, du moins c'est mon impression, en raison des réponses négatives des utilisateurs .

Même s'il n'y a aucun cas où un :: tête peut être confondu avec un chemin qui commence sur un identifiant précédent et a un :: interne, il n'est pas très distinct visuellement.

De plus, c'est moins suggestif. @ est un meilleur mnémonique. Avec un :: début, vous devez vous demander si c'est comme des chemins de noms de fichiers, où / début signifie root (si vous êtes sur un système Unixy), ou s'il s'agit d'une abréviation standard, où aucun début la chose voudrait dire "nous avons omis le nom parce que c'est relatif". Avec un instant de réflexion, vous pouvez voir que le premier a plus de sens, mais le fait est qu'il faut un instant de réflexion. @ (ou quelque chose comme ça) se distingue instantanément à la fois par le compilateur et le codeur, ce qui facilite la compréhension instantanée de ce qui se passe.

Comment un @ début est-il plus facile à distinguer qu'un :: ? :: est déjà un mécanisme établi à la fois en Rust et en C++ !

@rpjohnst - J'ai dit comment dans la phrase même à laquelle vous @ est distinct visuellement. Pour s'étendre : il vous saute aux yeux. Il n'y a aucun risque de confusion entre le positionnement leader et le positionnement interne dans votre modèle mental du flux de jetons.

@ est un tout nouveau jeton sans aucune signification, et il faudrait bien plus qu'"un instant de réflexion" pour le comprendre. Confondre un :: de premier plan avec un :: interne n'est pas un problème pour commencer - il n'y a aucune raison pour que quiconque prenne « un instant de réflexion » pour rejeter l'idée qu'un :: premier plan

@rpjohnst - Vos déclarations sont vraies compte tenu d'une formation suffisante sur ce que signifie :: (ce qui est fourni par l'expérience avec C++ ou Rust). Je parlais d'apprentissage et de différence intrinsèque. "Le même symbole utilisé dans un contexte différent" ne sera jamais aussi reconnaissable qu'un "symbole unique".

Je pourrais accepter un argument selon lequel cela ne vaut pas la peine de graver @ comme symbole unique dans un cas d'utilisation comme celui-ci où il existe une alternative tolérable.

@Ichoran : Je pense qu'ajouter un nouveau token pour une certaine sémantique ( @ ) à la grammaire Rust n'est pas une étape à prendre à la légère, et j'ai un léger soupçon que nous sommes trop près de le faire avec @nikomatsakis et la proposition des autres. D'une part, parce que nous ne pouvons alors pas le réutiliser à d'autres fins plus tard dans la vie du langage (je suppose que les chemins sont si répandus dans le code que le jeton @ pourrait apparaître à de nombreux endroits). Je me demande aussi quel est l'effet sur la perception de la complexité du code Rust. Pour un novice non habitué par exemple à C++, je crois (mais n'ayant pas de recherche à ce sujet) Rust est un langage avec une notation assez baroque et intimidante. L'un des objectifs stratégiques de cette année est d'optimiser la capacité d'apprentissage et, je suppose, l'accessibilité de Rust. Alors peut-être que nous devons en tenir compte lorsque nous imaginons @ parce que l'intuition est que cela se démarquerait dans le code (ce que @rpjohnst, je pense, remet en question à juste titre). Suis-je assez clair sur ce que je veux dire par là ?

(N'hésitez pas à corriger ou à clarifier tout ce que j'ai prétendu, car je n'ai tout simplement pas le temps de suivre de très près la discussion sur la grammaire de Rust.)

@est31

indépendamment du fait que j'aime ou non vos suggestions (je peux en fait vivre avec les deux), pouvons-nous s'il vous plaît nous en tenir à la RFC ?

En gros je suis d'accord. Je ne veux pas vraiment m'impliquer dans de grandes discussions en ce moment - c'est la période de mise en œuvre après tout ! -- mais je voulais mettre l'idée @ "là-bas" pour qu'elle mijote en arrière-plan. En partie parce que j'ai tendance à avoir des oublis, et écrire des choses m'aide à m'en souvenir plus tard.

Mon sentiment est qu'à ce stade, la bonne chose à faire est de :

  • Implémentation de la RFC à peu près telle qu'elle est écrite.

    • Nous pouvons, par exemple, adopter la suggestion de @rpjohnst de ::crate pour les chemins absolus, juste pour résoudre la ambiguïté de l'analyse, car cela semble être un très petit delta et augmente en fait la cohérence globale.

  • Acquérir de l'expérience en l'utilisant.
  • Revoyez la conception, en gardant à l'esprit les alternatives qui ont été proposées entre-temps, et prenez les décisions finales de stabilisation.

C'était l'esprit dans lequel j'avais l'intention d'écrire mon commentaire, même si je suppose que je n'ai pas été clair. Il aurait peut-être été préférable de le garder dans un dossier privé. :woman_shruging:

EDIT : De plus, je sais que @ et [] ont été collectés plus tôt, bien que je ne me souvienne pas si la notation @::foo été mentionnée auparavant pour être relative à la notation actuelle Caisse. Je ne veux donc pas revendiquer la paternité de l'idée.

OTOH, l'idée que j'ai mentionnée n'avait pas été soulevée auparavant, et n'est pas tant une modification de la RFC qu'une extension de celle-ci. Aussi, "La syntaxe finale pour les chemins absolus ; il y a plus de bikeshedding à faire ici dans un contexte où nous pouvons réellement essayer les différentes options." est explicitement répertorié comme une question non résolue dans le corps du problème. Je suis d'accord que, en général, nous devrions essayer d'éviter de remettre en cause les RFC acceptées, mais je ne pense pas que cette situation soit comparable à celle que nous avons eue avec, par exemple, des plages inclusives (pouah).

Voir aussi ce fil de discussion :

https://internals.rust-lang.org/t/the-great-module-adventure-continues/6678

Bienvenue dans un autre épisode de la Grande Aventure des Modules ! La dernière fois que nous nous sommes rencontrés, nos courageux aventuriers étaient enfin arrivés dans le pays légendaire, ayant accepté la RFC #2126. Là, ils prirent un bref répit et se préparèrent à commencer la Période Impl. Au cours de cette période, un travail considérable a été accompli et, en effet, les grandes lignes du système de modules ont été mises en œuvre. Mais voilà, il restait encore quelques questions à résoudre… et cela nous amène à ce fil de discussion.

Dans un langage moins fleuri : pendant la période d'implémentation, nous avons beaucoup progressé dans la mise en œuvre du RFC « Clarifier et rationaliser les chemins et la visibilité » (ainsi qu'un certain nombre de RFC connexes). En fait, nous avons fait presque trop de progrès – nous avons implémenté quelques variantes différentes, et j'aimerais lancer une discussion sur ce que nous voulons vraiment.

J'aimerais pouvoir un jour stabiliser cet excellent travail =) et cela nous obligera à choisir une des variantes... d'où le fil.

Personnellement, je suis fan de la syntaxe @ évoquée par @nikomatsakis. C'est concis et assez explicite. Nous allons devoir introduire une sorte de nouvelle syntaxe ici, donc mieux vaut un caractère spécial qu'un nom réservé comme crate (ugh).

On dirait que nous sommes en mesure de nous attaquer au deuxième pointeur externe maintenant, d'autant plus que https://github.com/rust-lang/cargo/issues/1311 est maintenant résolu (il devrait déjà être fermé, en fait). Je pourrais éventuellement m'attaquer à cela, avec un peu de mentorat et une décision sur la syntaxe @ vs crate . Les pensées?

Ajout de problèmes de suivi pour les deux peluches non implémentées.

Il me vient à l'esprit que nous avons un petit problème de compatibilité : si nous voulons que extern crate devienne implicite, il y a un changement décisif à faire pour que cela fonctionne -- extern crate force les caisses à être liées ; ce qui peut provoquer des erreurs si vous spécifiez des caisses supplémentaires dans Cargo.toml mais pas lib.rs qui ne se lient pas correctement (par exemple, panic=unwind caisses avec panic=abort, ou caisses qui exportent le même symbole). Avons-nous déterminé qu'il s'agissait d'une rupture non problématique ?

Il me vient à l'esprit que nous avons un petit problème de compatibilité : si nous voulons que la caisse externe devienne implicite, il y a un changement décisif impliqué dans le fait que cela fonctionne -- la caisse externe force les caisses à être liées ; ce qui peut provoquer des erreurs si vous spécifiez des caisses supplémentaires dans Cargo.toml mais pas lib.rs qui ne se lient pas correctement (par exemple, panic=unwind caisses avec panic=abort, ou caisses qui exportent le même symbole). Avons-nous déterminé qu'il s'agissait d'une rupture non problématique ?

La seule solution que j'ai vue jusqu'à présent est de ne lier implicitement une caisse que lorsque vous importez quelque chose de cette caisse, mais cela pose encore quelques problèmes. Les caisses peuvent exposer des fonctionnalités de nombreuses manières autres que la simple exportation de symboles de rouille à importer, telles que la liaison dans une certaine bibliothèque native ou l'exportation #[no_mangle] symboles extern crate est supprimé, la seule façon de forcer une telle caisse à être liée est de lui faire exporter un symbole de rouille placebo à importer selon les besoins. Je ne sais pas qui a pensé que c'était une meilleure idée de forcer les gens à utiliser une telle solution de contournement au lieu de s'en tenir à extern crate .

Oui, nous utilisons explicitement ce modèle dans Firefox -- il y a une caisse de niveau supérieur gkrust qui contient juste des instructions de caisse externes pour les caisses qui doivent être liées (celles-ci exposent des fonctions C externes écrites en Rust que Firefox appelle)

Vous pouvez toujours le faire fonctionner en demandant aux gens de use cratename; dans lib.rs pour forcer cela.

Et si vous disposiez d'un attribut #![link_crates(stylo,webrender)] à cette fin ? Contrairement à extern crate , cela n'ajouterait pas la caisse à l'arbre de noms. Lui donner un nouveau nom indiquerait clairement aux lecteurs que vous incluez les caisses pour le lien uniquement et que la déclaration ne doit pas être supprimée, alors que extern crate devrait le faire.

Cela résout le problème inverse cependant?

Oh, je vois, pour les personnes de l'époque 2015, cela leur permet de mettre à jour leur code sans changer d'époque.

Mais cela signifie que _tout le monde_ devrait utiliser une clé link_crates . Ce n'est pas idéal.

Que diriez-vous d'avoir un attribut #![link_crates(stylo,webrender)] à cette fin ? Contrairement à la caisse externe, cela n'ajouterait pas la caisse à l'arbre de noms.

Qu'en est-il des caisses qui pourraient être utilisées soit comme caisses à liens uniquement, soit comme caisses avec des symboles Rust, soit les deux ?

@whitequark si vous utilisez des symboles de ces caisses, vous obtiendrez un lien gratuit comme c'est déjà le cas maintenant. L'attribut serait sur le site d'utilisation afin que vous, en tant qu'utilisateur, décidez comment utiliser la caisse.

@Manishearth

Mais cela signifie que tout le monde devrait utiliser une clé link_crates. Ce n'est pas idéal.

Non. Je n'ai pas assez bien formulé ma proposition. Je veux garder intacte la partie où use cratename::item; a le même effet que link_crates . La fonction link_crates ne doit être utilisée que si vous n'avez besoin d'aucun élément de la caisse mais que vous avez besoin du lien. Si vous importez des éléments de la caisse, vous obtiendrez un lien semblable à celui proposé par la RFC.

Je ne pense tout simplement pas qu'avoir use cratename; dans votre code à cette fin soit une bonne chose car cela confondrait les lints et (le plus important) les lecteurs/écrivains de code, et je pense donc qu'il devrait y avoir une fonctionnalité dédiée pour ce légitime (mais rarement) cas d'utilisation.

@est31 Bikeshedding sur la syntaxe pour link_crates , au lieu de l'avoir comme attribut, pourquoi ne pas faire quelque chose comme extern crate foo; ?

@retep998
Bonne idée! :le sourire:
https://github.com/rust-lang/rfcs/pull/2166 a même introduit extern crate foo as _; pour éviter d'introduire le nom de la caisse dans la portée/le module pour les caisses à liaison uniquement.

@ est31 Bikeshedding sur la syntaxe de link_crates, au lieu de l'avoir comme attribut, pourquoi ne pas faire quelque chose comme extern crate foo ;?

Le but est de se débarrasser de la syntaxe extern crate à long terme, cependant.

@alexreg Le but est de le rendre inutile dans le cas courant. Cela ne signifie pas qu'il doit être entièrement éradiqué, c'est peut-être toujours une bonne solution pour le cas limite d'une caisse qui doit être liée sans qu'aucun élément Rust de celle-ci ne soit utilisé. (Et de toute façon, il vivra tant que le compilateur prendra en charge les époques plus anciennes.)

@SimonSapin Mais à l'avenir, s'il ne s'agit que d'un cas limite, peut-être qu'avoir une syntaxe spéciale pour cela n'a pas de sens, et un attribut (comme proposé ci-dessus) aurait plus de sens.

Je pense toujours que use foo ou use foo as _ devrait suffire ici, vraiment

D'accord avec @Manishearth.

Résumant mon point de vue sur extern crate; :

Avantages :

  • extern crate vous donne une liste complète des caisses utilisées en haut de votre bibliothèque. Maintenant, avec les caisses normales, ce n'est pas si pertinent qu'il y a Cargo.toml, mais si vous avez des exemples, c'est très utile car cela vous donne une liste de caisses à importer. Réfléchissez simplement, et si vos exemples importaient simplement un sous-ensemble de vos dépendances de développement ? Cela présente des avantages considérables lorsque vous essayez de comprendre l'API d'une nouvelle caisse, c'est-à-dire des avantages en matière d'apprentissage. D'un autre côté, vous pouvez mentionner que extern crate peut apparaître n'importe où dans la caisse, la liste n'a donc pas à être exhaustive, mais pour les exemples, c'est moins pertinent. Nous pouvons toujours modifier la caisse externe pour ne travailler que dans la racine de la caisse si nous le souhaitons.

Désavantages:

  • extern crate est un inconvénient mineur car cela signifie plus de choses à taper lors de l'ajout d'une caisse. Je pense que c'est la raison pour laquelle beaucoup de gens sont contre extern crate mais pour moi ce n'est pas la raison motivante.
  • Je vois que extern crate fait partie d'un échange : nous abandonnons extern crate mais gagnons la distinction entre l'importation de la propre caisse et l'importation de la caisse extérieure. C'est une fonctionnalité beaucoup plus utile et l'OMI l'emporte sur les inconvénients d'apprentissage avec des exemples/tests de code. C'est la raison pour laquelle je suis d'accord avec la suppression de extern crate .

extern crate vous donne une liste complète des caisses d'occasion en haut de votre bibliothèque. Maintenant, avec les caisses normales, ce n'est pas si pertinent qu'il y a Cargo.toml, mais si vous avez des exemples, c'est très utile car cela vous donne une liste de caisses à importer.

Je ne vois pas en quoi cela est pertinent pour la discussion ici; c'est un point contre un RFC déjà fusionné.

@Manishearth Je @ retep998 ici qui a en quelque sorte suggéré de garder la caisse externe. Et non, un point n'est pas illégitime ou hors de propos simplement parce qu'il est contre un RFC déjà fusionné. Il faut réfléchir et connaître les avantages et les inconvénients des décisions. Nous pouvons toujours, par exemple, supprimer le crate externe de lib.rs mais le conserver pour hello_world.rs pour les avantages de l'ergonomie et de la facilité d'apprentissage (pour les utilisateurs de la bibliothèque, pas pour ses auteurs).

Ce n'est pas pertinent parce que la chose en cours de discussion (dans le commentaire de Peter auquel vous répondez) concerne les caisses à liens uniquement ; qui sont un cas d'utilisation suffisamment spécialisé dans lequel « répertorier toutes vos caisses externes en haut » est un avantage marginal. Surtout si vous avez des dépendances qui ne sont _pas_ des caisses de liens uniquement (ce qui n'était pas vrai pour Firefox, mais c'est maintenant).

Si votre point est plus général sur le fait que la chose implicite des caisses externes ne s'applique pas aux tests (et pas spécifiquement aux caisses à liens uniquement), c'est un point intéressant, mais je ne suis pas vraiment d'accord avec cela parce que ça va être plus déroutant quand il n'est utilisé que dans la moitié du code.

Donc, si je ne me trompe pas, le seul point d'implémentation restant ici est le n° 48719. Est-ce que quelqu'un s'attaque à ça maintenant? Sinon, je peux essayer, je suppose...

Oui, nous essayons des trucs dans #50260

Le sam. 28 avr. 2018, 09:15 Alexander Regueiro [email protected]
a écrit:

Donc, si je ne me trompe pas, le seul point de mise en œuvre restant ici est

48719 https://github.com/rust-lang/rust/issues/48719 . Est-ce que quelqu'un

s'attaquer à ça maintenant? Sinon, je peux essayer, je suppose...

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/rust-lang/rust/issues/44660#issuecomment-385187379 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/ABivSMyg6L4nQ1O7nMcvY4JCGjWKRiq3ks5ttJWhgaJpZM4PaPWi
.

48722 est fait. @Manishearth pourriez-vous mettre à jour l'OP, s'il vous plaît :)

@mark-im @Manishearth https://github.com/rust-lang/cargo/issues/1311 est également terminé, alors cela vaut peut-être la peine de changer ce point en une case à cocher et de la cocher. Je suis curieux cependant : quelle est l'approche quand Cargo n'est pas utilisé, à l'avenir ? (Ce n'est pas que quelqu'un de sensé évite Cargo...)

@alexreg Le mécanisme utilisé par Cargo pour dire à rustc de renommer une caisse est également accessible aux personnes n'utilisant pas cargo : --extern name_rustc_sees=path_to_dep.rlib .

On dirait que nous aurons bientôt terminé toute la phase de mise en œuvre – lorsque https://github.com/rust-lang/rust/pull/47992 atterrira, en fait. Est-ce que je manque quelque chose ? Heureux d'aider à faire avancer les choses s'il reste des choses à faire.

Ouais, c'est en route. Je dois conclure ce que je ferai probablement plus tôt
la semaine prochaine.

Le jeu. 3 mai 2018, 19:51 Alexander Regueiro [email protected]
a écrit:

On dirait que nous aurons bientôt terminé toute la phase de mise en œuvre - quand

47992 https://github.com/rust-lang/rust/pull/47992 atterrit, en fait. Un m

il me manque quelque chose ? Heureux d'aider à faire avancer les choses s'il y a des morceaux et
bobs restant à faire.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/rust-lang/rust/issues/44660#issuecomment-386494018 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/ABivSDYFonDWvxZEdxWXoykroaL2mJPxks5tu8I_gaJpZM4PaPWi
.

@Manishearth Bonnes choses.

@aturon avec https://github.com/rust-lang/rust/pull/50260 a atterri, tout est-il mis en œuvre ?

Quelqu'un a-t-il le lien vers le plan qui a été proposé après le RFC ? Celui qui ressemble le plus à ce qui a été réellement mis en place ? (où les importations de caisses --extern sont ajoutées au prélude, et etc.)

Puisqu'il s'agit d'un changement si important, peut-être que le RFC devrait être mis à jour ?

Les RFC ne sont généralement pas mis à jour ; ils ne sont pas une spécification finale. Ils sont un
outil de recherche de consensus.

Le lun 18 juin 2018 à 21:43, Qui ? Moi?! [email protected] a écrit :

Puisqu'il s'agit d'un changement si important, peut-être que le RFC devrait être mis à jour ?

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/rust-lang/rust/issues/44660#issuecomment-398247665 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AABsij-Iwwb7vf4qBrsq9KFFqhuIbkVBks5t-Fc3gaJpZM4PaPWi
.

@mark-im Ce discours reste dans l'esprit du RFC. Comparez le résumé de la RFC avec ce post, c'est la plupart du temps le même, au-delà de petits détails. Il y a eu des RFC où l'équipe a décidé de faire un changement totalement différent, mais ce n'est pas l'un d'entre eux.

Tout cela est vrai, mais ce serait bien que tout soit au même endroit. Je comprends cependant le défi logistique que cela représente...

🔔 🔔 Notez qu'un aperçu de l'édition 2018 est maintenant prêt et inclut les modifications du système de module. S'il vous plaît jeter un oeil et laisser des commentaires ici!

@aturon La dernière mise à jour et la dernière réunion du groupe de travail sur le module ont abouti à https://internals.rust-lang.org/t/the-great-module-adventure-continues/6678/205 , qui disait spécifiquement " réduit à une seule proposition de base, avec deux variantes". Au meilleur de ma connaissance, c'était toujours vrai. J'avais l'impression que nightly avait implémenté les deux, via des indicateurs de fonctionnalité, pour prendre en charge l'expérimentation avec les deux.

Il semble que l'édition ait choisi l'une des deux variantes, l'ait choisie pour la prise en charge sans indicateurs de fonctionnalité et l'ait documentée dans le guide d'édition. Où cela a-t-il été discuté ? Parce que pour autant que je sache, ni le groupe de travail du module ni l'équipe lang n'y étaient impliqués.

Veuillez consulter https://internals.rust-lang.org/t/relative-paths-in-rust-2018/7883 pour une nouvelle proposition, construite à partir de l'aperçu 2018. En particulier, cette proposition fournit plus de cohérence et d'uniformité entre le module racine et les sous-modules, et utilise la même résolution de nom à la fois dans les instructions use et dans les utilisations directes des chemins dans le code.

Salut, juste mes 2 cents sur le ::some::path vs crate::some::path - Je préfère ce dernier, principalement parce qu'il est plus facile à lire en anglais simple et ne laisse pas de ponctuation folle à gauche.

S'il vous plaît jeter un oeil et laisser des commentaires ici!

J'espère que c'est ce que tu voulais dire. Après avoir examiné un grand changement dans la caisse à terme, dans lequel tous les pub(crate) s ont été changés en crate , je suis plus convaincu qu'utiliser crate fois dans les importations et comme visibilité le modificateur ne semble pas naturel et déroutant.

crate enum Either<T, U> {
    A(T),
    B(U),
}

Je trouve cela particulièrement déroutant lorsque les deux sont utilisés ensemble :

crate use crate::foo;

Comme je l'ai mentionné dans le problème de lint pour essayer de nous faire basculer tous , cela me rendrait très triste, et je voudrais probablement qu'un lint tiers soit mis en œuvre pour faire le contraire, à utiliser dans les bibliothèques que je gère : arrêter les gens de la conversion de pub(crate) à seulement crate .

(Remarque : je ne commente aucune autre partie des modifications, qui semblent bonnes pour la cohérence, uniquement le changement de pub(crate) à simple crate .)

@seanmonstar Avec les modifications supplémentaires proposées au système de modules dans la prochaine édition, je m'attends à ce que crate::foo devienne plus rare, et crate use crate:: semble être un événement particulièrement rare.

Avec le système de modules dans l'aperçu initial de 2018, vous auriez besoin d'écrire crate:: même pour les références plus profondes dans votre caisse. Avec le système de module proposé, vous auriez seulement besoin crate:: pour les références dans votre caisse (par exemple, de foo.rs à lib.rs, ou de foo / bar.rs à foo.rs), mais pas pour les références vers le bas dans votre caisse (par exemple, de lib.rs à foo.rs, ou de foo.rs à foo/bar.rs). Et généralement, je m'attendrais à ce que les réexportations (que ce soit via pub use ou crate use ) réexportent quelque chose d'un module plus profond dans un module de niveau supérieur, et non l'inverse.

Donc, en général, je serais surpris de voir crate use crate::foo; .

Et pourtant, dans un projet sur lequel je travaille, j'ai exactement ce scénario. J'ai un module qui contient plusieurs helpers "génériques", puis un autre module définissant un trait de base + des combinateurs, et comme ils utilisent quelques helpers génériques, j'ai réexporté pour m'aider dans d'autres parties du Caisse:

Actuellement:

// in filter/mod.rs
pub(crate) use ::generic::{Combine, Func};

// in filters/foo.rs
use ::filter::{Filter, Func};

La peluche voudra que je change ceci en :

// in filter/mod.rs
crate use crate::generic::{Combine, Func};

Donc, je n'essayais pas de proposer une hypothèse que personne ne rencontrera jamais. C'est vrai.

Je suis entièrement d'accord avec @seanmonstar. Ne surchargeons pas ce mot-clé sauf si nous y sommes obligés (ce que nous ne faisons pas).

Oui, vous avez raison, les réexportations _généralement_ bouillonnent, mais être réexportées _latéralement_ est aussi une chose, comme le souligne Sean. C'est quelque chose que j'envisage de faire également pour la caisse servo-média, car les fichiers sont assez bien divisés, mais cela signifie simplement beaucoup d'importations communes dans toutes nos implémentations de nœuds.

Sera-t-il possible de continuer à déclarer ce qui est utilisé dans un module et nécessitera éventuellement une utilisation explicite, peut-être en tant qu'attribut de caisse ? Je préfère être capable de savoir en regardant un fichier source ce qu'il contient. Avoir quelques lignes d'importations au niveau racine au début d'un fichier source permet de donner un certain contexte pour ce qui se passe réellement à l'intérieur, plutôt que d'avoir toutes les dépendances externes implicitement dans la portée, et aide grandement lors de la refactorisation.

Après avoir essayé la conversion sur l'une de mes caisses, je voulais mentionner comme d'autres que j'ai vu en parler, je ne suis pas convaincu d'utiliser crate comme modificateur de visibilité au lieu de pub(crate) est une amélioration. Mon raisonnement ici est que le surnom de caisse est assez largement utilisé, et le simple fait de le coller devant des objets le rend un peu désordonné (cela me rappelle la soupe de mots-clés que vous obtenez dans certaines langues, comme public static void main() Java -- au moins Rust a le type de retour à la fin). pub(crate) conserve au moins le pub pour rendre plus évident que crate traite de la visibilité dans ce contexte.

Voici une autre instance que je viens de rencontrer et qui combine le mot-clé crate à la fois dans un modificateur de visibilité et dans un chemin, ce qui semble encore plus probable que l'instance crate use crate... .

Courant:

pub(crate) struct Bar {
    pub(crate) foo: ::Foo,
}

pub(crate) struct Baz(pub(crate) ::Foo);

Avec les modifications apportées à ce problème de suivi :

crate struct Bar {
    crate foo: crate::Foo,
}

crate struct Baz(crate crate::Foo);

Personnellement, je trouve que la nouvelle version est plus déroutante que la méthode actuelle.

Quand j'ai lu pour la première fois la RFC pour convertir pub(crate) en crate j'ai pensé que cela sonnait comme une évidence. pub(crate) semble très étrange par rapport au reste de la syntaxe Rust associée dans ce domaine.

Mais...

Après avoir converti un petit jeu Piston en Rust 2018 et l'avoir vu de mes propres yeux , je dois admettre que je suis sympathique aux @seanmonstar et d'autres qu'avoir un simple crate saupoudré partout était cognitivement choquant. Je ne sais pas si je m'y habituerais naturellement avec le temps ou non.

Comme d'autres l'ont dit, il semble que le mot-clé signifie quelque chose de très différent dans les deux contextes.

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

Je veux être clair, j'aime vraiment le reste de cette proposition (les mises à jour du système de module).

Je suis sympathique que pub(crate) semble un peu lourd et aussi étrange, mais aussi un nu crate se sent un peu hors de propos.

Pourrions-nous simplement envisager un mot-clé différent ici au lieu de réutiliser crate ?

@neon64 Suggéré internal ce qui semble raisonnable, mais il pourrait y en avoir d'autres. Puisque nous pouvons ajouter des mots-clés dans Rust 2018, nous avons maintenant la possibilité d'en tenir compte.

internal me semble plus lourd que pub(crate) . Ce n'est pas plus court et c'est un nouveau mot-clé.

Que diriez-vous de int ? :P

À l'intérieur ( ins ), interne ( int ), protégé ( pro ), local ( loc ), secret ( sec ), inner ( inn ) il existe de nombreuses alternatives au mot-clé crate .

Est-ce que int sera déroutant pour les développeurs C/C++ ? (mot-clé entier)

en tant que programmeur, lorsque vous voyez pub, vous le traitez comme public, si vous souhaitez introduire un autre niveau de visibilité, vous avez besoin qu'il soit un adjectif pour rester cohérent. Pour autant que je me souvienne, pub signifiait publier initialement et dans les deux cas, pub (crate) semble plus naturel. Crate est juste un mot-clé étrange pour cela.
Je pense qu'il vaut mieux laisser pub(crate) tel quel ou ajouter une abréviation à partir de l'adjectif.

Je pense aussi que la difficulté à nommer vient du fait que pub est une abréviation, si c'était public, je pense que ce ne serait pas un problème de l'appeler privé ou interne et de l'oublier.

Personnellement, je ne vois pas le problème avec pub(crate) . La syntaxe est claire et sans ambiguïté à première vue et cohérente avec la vraie rouille. Je ne pense pas que vous ayez à taper cela assez souvent pour que 5 frappes supplémentaires soient un problème.

@UtherII

La raison pour laquelle nous avons besoin d'un nom court pour pub(crate) est que beaucoup (peut-être même la plupart ) des utilisations actuelles de pub seront remplacées par celui-ci.

Dans Rust 2018, l'utilisation de pub pour des éléments effectivement privés (car ils apparaissent dans des modules privés) sera un avertissement. On devrait plutôt utiliser pub(crate) pour de tels objets. Cette convention améliorera la lisibilité du code : un élément est visible pour les autres caisses si et seulement s'il est marqué pub , alors qu'actuellement, il peut ne pas être évident en un coup d'œil s'il est visible pour les autres caisses.

Désolé, j'ai accidentellement créé un nouveau problème pour cela plutôt que de répondre à ce fil. Oups, je suis plutôt nouveau sur github et j'ai simplement cliqué sur un bouton qui m'a amené à me connecter à ce que je pensais répondre ici mais qui créait en fait un nouveau problème. Je vais coller ce que j'ai écrit dans le nouveau numéro ici, et mon nouveau numéro peut être supprimé, désolé pour ça.

Étant donné que le manuel d'édition suggérait aux gens de laisser des commentaires ici, j'ai décidé de le faire.

Cela ne me dérange pas vraiment que ce soit crate :: ou :: pour accéder aux éléments à partir de la racine de la caisse. :: est ce qui est déjà la syntaxe cependant, donc s'il est possible d'avoir les deux crate :: et :: je pense que les deux devraient être utilisés. La façon dont je le vois est que le nouveau système de caisse suggéré concernant les chemins est essentiellement équivalent à l'ancienne syntaxe, la seule différence étant que vous n'avez plus besoin d'utiliser le mot-clé extern, et les choses sont plus accessibles plutôt que d'avoir besoin de les utiliser explicitement dans les sous-modules, ils sont essentiellement importés implicitement partout.

Le seul autre ajout semble être que vous démarrez la racine de la caisse avec crate :: plutôt que ::. Je préfère le démarrer avec seulement ::, car cela est cohérent avec la façon dont je l'ai appris à l'origine, mais je peux voir des personnes qui n'ont pas encore appris le système de modules trouvant le démarrage avec crate :: plus intuitif. Pourquoi ne pas autoriser les deux formes de syntaxe ? Y a-t-il une raison qui rend impossible les deux ? Si les deux peuvent être soutenus, j'approuve totalement le fait de les soutenir tous les deux. Si un seul peut être pris en charge, je suis plus enclin à :: tout comme c'est ce à quoi je me suis habitué, même s'il peut être plus facile pour les débutants de l'apprendre en tant que caisse :: et je peux mettre à jour trivialement ma compréhension de celui-ci être tel, alors peut-être que ma motivation est égoïste.

Donc, essentiellement, je m'en fiche finalement, mais personnellement, je préfère ::, mais je pense que soutenir les deux serait idéal, mais si l'on doit être sélectionné et que les gens pensent que commencer avec crate :: est supérieur pour les débutants, alors je ne pas d'objection à cela.

Comment #[path] censé fonctionner avec des modules imbriqués dans Rust 2018 ? (https://github.com/rust-lang/rust/issues/35016#issuecomment-409185342)

IIUC, pour le moment, étant donné deux fichiers src/lib.rs et src/bar.rs , il n'y a pas de X qui puisse être remplacé dans :

mod foo {
    #[path = "X/bar.rs"]
    mod bar;
}

tel que le module bar.rs sera trouvé, car le chemin vers bar.rs sera toujours src/foo/X/bar.rs ce qui est invalide car le répertoire foo n'existe pas.

Étant donné que nous cherchons un bon nom pour un remplacement de pub(crate) et que l'équipe de base recherche toujours des commentaires, j'aimerais partager mon expérience et faire une suggestion.

Dans une caisse que j'ai écrite, j'ai trouvé exaspérant de taper pub(crate) partout. Je l'ai donc simplement raccourci à pub et exporté par inadvertance de nombreux symboles qui n'avaient pas besoin d'être visibles à l'extérieur de la caisse. Oups. 😛 (Dans mon cas spécifique, ce n'est pas vraiment un problème, car la caisse est interne et non publiée, mais quand même ! La commodité plutôt que l'exactitude.) Alors oui, je crois fermement que nous avons besoin de quelque chose de mieux qu'un mélange de deux mots-clés pour transmettre une visibilité au niveau de la caisse .

Mais je ne crois pas que crate soit le bon mot-clé pour cela (voir ci-dessus pour les commentaires des autres sur ce sujet), et j'ai l'impression que d'autres mots-clés suggérés manquent le point en abordant le problème du point de vue de la racine de caisse; le problème réside dans la perspective du module, c'est-à-dire la ligne de code spécifique contenant le mot-clé. En d'autres termes, le code n'essaie pas de fournir une "localité de caisse", il essaie d'exporter la référence du module où elle est définie.

En ce sens, j'aime le mot-clé export (même s'il est possible de le confondre avec extern , mais c'est peut-être discutable puisque extern crate est mort ?) export struct Foo; semble très lisible et s'aligne avec d'autres langues (ish). Je n'ai trouvé aucune mention de export comme mot-clé, dans cette RFC ou ailleurs. Donc il y a aussi ça pour ça.

Pour être complet, il couvre les cas d'utilisation évoqués par @johnthagen , et al. :

export use crate::generic::{Combine, Func};

// Or even better using relative paths
export use ::generic::{Combine, Func};
export struct Bar {
    export foo: crate::Foo,
}

export struct Baz(export crate::Foo);
use crate::menu::{Sound, Volume};

export mod color;

// ...

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

Cela dit, je suis en faveur de tuer pub(crate) avec le feu. Je préfère même crate , FWIW.

@parasyte Le problème que je vois avec export est qu'il pourrait être confondu avec "cette caisse exporte ____" (c'est à ça que sert pub ), mais je vois comment vous plaidez pour un perspective différente.

Il semble que la plupart des gens s'accordent pub(crate) dire que crate , qui est maintenant utilisé dans d'autres contextes, puisse être choquant en remplacement. S'assurer que nous avons pleinement pris en compte d'autres mots-clés (potentiellement nouveaux) semble être une très bonne utilisation du temps avant que Rust 2018 ne définisse cela dans le marbre.

Je n'ai pas entendu de commentaires "officiels" si cela est toujours ouvert à la discussion?

Dans l'intérêt d'introduire quelques mots supplémentaires dans le sens de la suggestion de @johnthagen que export ressemble plus à pub qu'à pub(crate) ):

shared use ::generic::{Combine, Func};
shared struct ColoredText {
    export color: types::Color,
    export text: &'static str,
}
global use ::generic::{Combine, Func};
global struct ColoredText {
    export color: types::Color,
    export text: &'static str,
}

Nous pourrions également suivre les traces de Java et utiliser quelque chose comme protected , mais je ne suis pas sûr que ce soit particulièrement facile à comprendre. Il y a aussi local (au sens de crate-local), mais je pense que global est en fait moins susceptible de prêter à confusion (par exemple, local pourrait être _file_-local).

Que penseraient les gens de pub(cr) ou même de cr ?

Utiliser crate semble trop beau pour être ignoré. C'est déjà un mot-clé, son utilisation précédente dans extern crate va disparaître. Son autre utilisation est déjà liée à la visibilité pub(crate) .

Si vous louchez un peu, utiliser caisse comme adjectif ne semble pas si déconcertant. Des mots tels que « maison » peuvent très bien être utilisés comme adjectifs. IANAEnglishProfesseur.

Je pense que réexporter un élément visible de caisse n'est pas super problématique. Personnellement, je n'ai réexporté un élément que dans un parent direct du module qui le définit, ce qui signifie que vous voulez (probablement) utiliser self au lieu de crate (le cas d'organisation de code de seanmonstar nonobstant ). Par exemple.

    mod detail {
        crate struct Foo;
    }

    crate use self::detail::Foo;

L'utilisation de crate comme visibilité combinée à un chemin absolu vers un type (en utilisant à nouveau l'exemple de seanmonstar) semble plus problématique : crate struct Foo(crate crate::Bar); par opposition à pub(crate) struct Foo(pub(crate) ::Foo); . Mon seul espoir est que cette construction ne soit pas populaire et que la transition ne crée donc pas cette soupe de caisse. Les utilisateurs peuvent éviter cela en important :

use crate::Bar;

crate struct Foo(crate Bar);

J'aime la suggestion de share ou quelque chose comme ça. give , provide , deliver , offer , serve , post , forward .. S'il doit s'agir d'un adjectif, ceux-ci peuvent tous être transformés avec un suffixe : shared , givable , providable , etc.

Pour reprendre JavaScript un instant, ES6 n'a même pas de concept de package par rapport au module intégré au langage. Il n'y a que des modules. Le mot-clé export dans ES6 exporte toujours la référence du module ; c'est alors à un autre module de import référence par chemin s'il veut l'utiliser.

Ce n'est pas très différent de pub et use , respectivement. et je suppose que c'est de là que viendrait une partie de la confusion avec l'utilisation d'un mot-clé export . pub(crate) est en fait une sorte de niche. C'est pourquoi j'ai choisi d'utiliser uniquement pub dans le passé. ;(

Le problème du modificateur de visibilité crate a été extrait au #53120. D'autres débats et décisions devraient se poursuivre là-bas.

Le problème des modifications de mod.rs a été extrait au #53125. D'autres débats et décisions devraient se poursuivre là-bas.

Le problème de la dépréciation de extern crate ainsi que d'avoir use crate_name::foo et crate_name::foo Just Work™ a été extrait sur https://github.com/rust-lang/rust/ numéros/53128. D'autres débats et décisions devraient se poursuivre là-bas.

La question de la sélection d'un système de chemin de module a été extraite sur https://github.com/rust-lang/rust/issues/53130.

Après avoir extrait tous les éléments de ce problème dans des problèmes distincts ; Je ferme par la présente celui-ci.

@Centril : https://doc.rust-lang.org/unstable-book/print.html#extern_prelude liens ici. Où est-ce que cela est discuté? Si cette information est effectivement manquante, pourriez-vous l'ajouter à l'OP ?

@sanmai-NL pouvez-vous me rafraîchir la mémoire sur ce qu'était le "prélude externe" ?

S'il ne s'agit que de la possibilité de faire use some_crate::foo::bar; cela devrait être https://github.com/rust-lang/rust/issues/53128.

Certaines d'entre elles sont discutées sur https://github.com/rust-lang/rust/issues/54230.

@sanmai-NL Je pense que ce problème concerne principalement les diagnostics.

extern_prelude est crate_name::foo::bar dehors des chemins use (importation).

@Centril

pouvez-vous me rafraîchir la mémoire sur ce qu'était le "prélude externe" ?

En général, "prelude" est actuellement utilisé pour tous les noms qui sont dans la portée de l'ensemble de la caisse et non attachés à un module spécifique. (Il y en a beaucoup en fait.)

@petrochenkov Alors, quel est le prélude "externe" par rapport à cela?

@alexreg
Les caisses passées avec --extern sont dans la portée de l'ensemble de la caisse sans être attachées à un module spécifique.

Ce serait formidable si ces pépites d'informations, aussi volatiles soient-elles, soient enregistrées dans une source officielle de documentation. Esp. s'il y a des mentions extérieures du concept, par exemple dans le livre Unstable. Je ne dis pas que les mainteneurs qui implémentent ces concepts devraient le faire, cependant.

@petrochenkov Merci, c'est logique.

Après avoir extrait tous les éléments de ce problème dans des problèmes distincts ; Je ferme par la présente celui-ci.

@Centril Tracking problèmes dans la version bêta actuelle, lien ici. Souhaitez-vous mettre à jour le commentaire d'origine avec les informations les plus récentes afin que les gens n'aient pas à épeler les commentaires ?

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

Questions connexes

nikomatsakis picture nikomatsakis  ·  331Commentaires

Leo1003 picture Leo1003  ·  898Commentaires

withoutboats picture withoutboats  ·  308Commentaires

nikomatsakis picture nikomatsakis  ·  210Commentaires

nikomatsakis picture nikomatsakis  ·  412Commentaires