Rust: (Модули) Проблема с отслеживанием ящика как модификатора видимости.

Созданный на 6 авг. 2018  ·  91Комментарии  ·  Источник: rust-lang/rust

Это проблема дополнительного отслеживания для RFC «Уточнение и оптимизация путей и видимости» (rust-lang/rfcs#2126).
рассматривая вопрос о crate как модификаторе видимости.

Нерешенные вопросы:

  • [ ] Как разобрать struct Foo(crate ::bar) ?
A-visibility B-RFC-approved B-RFC-implemented B-unstable C-tracking-issue T-lang

Самый полезный комментарий

Я лично не против написать pub(crate) , намерение кажется очень явным.
Пример, приведенный @johnthagen , действительно больно видеть (используя 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; особенно кажется запутанным, вам определенно нужно немного подумать о том, что там происходит.

Все 91 Комментарий

Комментарии о crate как модификаторе видимости:

Разбор неоднозначности

Неестественно / Путаница / Не улучшение

Хорошая идея

pub(extern) вместо этого

велосипедный сарай

Ранний превью

Выделенный поток

Лично я очень поддерживаю crate в качестве модификатора видимости и делюсь здесь комментарием @stepancheg . Я думаю, что мы должны поощрять меньшую и более строгую видимость, и crate делает именно это.

Я лично не против написать pub(crate) , намерение кажется очень явным.
Пример, приведенный @johnthagen , действительно больно видеть (используя 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; особенно кажется запутанным, вам определенно нужно немного подумать о том, что там происходит.

Некоторые из этих примеров очень похожи на C static esque-, но на самом деле удивительно различны.

Пример из-за @johnthagen мне не кажется плохим. На самом деле, это читается естественно, и мне очень нравится симметрия. В каком-то смысле это красиво.

Если читабельность:

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

становится проблемой; затем IDE/редактор, понимающий синтаксис Rust, может выделить токены crate в разных позициях разными цветами. Это должно хорошо прояснить разницу, я думаю.

crate как модификатор видимости определенно странный: он использует очень специфичное для ржавчины ключевое слово для вещи, которая не специфична для ржавчины. Kotlin и C# используют для этого internal .

Я лично хотел бы повторно использовать pub для crate-visible и использовать более кричащий синтаксис для видимого мира, например pub* или pub! .

Это поднималось раньше, но я думаю, что коренные проблемы, которые я вижу, следующие:

  1. crateсуществительное . Я думаю, что pub(crate) выглядит длинным и странным, поэтому я полностью поддерживаю замену его на что- то , но с ним действительно было связано общедоступное прилагательное, поэтому грамматически оно выглядело лучше.
  2. crate теперь используется в качестве привязки для импорта «этого ящика», что означает нечто иное, чем «где бы это ни было определено, оно также явно экспортируется из этого ящика».
// 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,
}

По сравнению с примером использования @matklad internal из 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,
}

Я не говорю, что internal — правильное ключевое слово (Rust любит очень короткие аббревиатуры, а int , к сожалению, полон путаницы с C/C++/Java), но лично я думаю, что второй пример сразу читабельнее.

Я также думаю, что ключевое слово видимости crate будет сбивать с толку людей , перешедших на Rust с других языков. Если даже многие из нас, достаточно вовлеченных в Rust, чтобы комментировать эти темы, будут возмущены, я должен представить, что это столкнет с толку и людей, плохо знакомых с Rust.

Немного более длинный синтаксис pub(crate) может не иметь большого значения, если бы не становился предупреждением/ошибкой наличия элементов pub , недоступных за пределами ящика. Я лично хочу, чтобы, если бы у меня был pub(crate) struct Foo { ... } , компилятор мог бы понять, что все pub fn в impl Foo явно недостижимы, и не беспокоить меня по этому поводу.

Я считаю, что в настоящее время в Rust 2015 это просто занятая работа, если я когда-либо отмечаю тип от pub struct Foo до pub(crate) struct Foo , как компилятор затем кричит во всех местах, где какой-то другой pub fn s существуют с использованием внезапного типа pub(crate) , когда проблема не реальна, потому что другой тип также pub(crate) .

Я также нахожу идею @matklad перепрофилировать pub как общедоступный ящик и использовать export или что-то в этом роде для экспорта, видимого миру. Но может быть, это слишком большое расхождение для издания?

Перед текущей версией предлагалось перепрофилировать pub как crate-public и добавить новую видимость для world-public. Такое изменение существующей семантики было сочтено слишком радикальным даже для редакции, поэтому pub теперь сохраняет свое текущее значение.

Мне кажется, меньше обсуждалось и рассматривалось перепрофилирование pub исключительно с помощью lint. Возможно, мы могли бы переключить lint с «предупреждать о pub , которые недоступны за пределами ящика» на «предупреждать о pub , которые доступны за пределами ящика», и добавить совершенно необязательный pub(extern) / export ключевое слово. То есть не меняйте никакой семантики, просто добавьте синтаксис подавления ворса.

Я подозреваю, что это будет менее разрушительным, исходя из предположения, что общедоступных в мире элементов меньше, чем общедоступных в ящиках. Это также сохранило бы интуитивное (хотя и немного неправильное) значение pub как «экспорт из текущего модуля», вместо того, чтобы показывать всем истинное поведение видимости.

Rust любит очень короткие аббревиатуры, а int , к сожалению, полна путаницы с C/C++/Java.

FWIW, хотя он сохраняет только два символа, если бы мы хотели сократить internal , «правильной» аббревиатурой, вероятно, по аналогии с extern al было бы intern . К сожалению, это также существительное с общепринятым, другим значением. Ну что ж.

@glaebhoerl intern — хороший вариант! ❤️

Симметрия с extern действительно хороша, и IMO значительно уменьшит потенциальную путаницу с формой существительного intern .

Он короткий (всего на 1 символ больше, чем crate ) и не конфликтует с use crate:: .

Обновленный пример будет выглядеть так:

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

Я упоминал об этом раньше, но я не уверен, в чем проблема с существительными, используемыми в качестве прилагательных?

Напомним: существует множество существительных, которые можно использовать в качестве прилагательных, например. домашняя кошка, компьютерная мышь, компьютерный стол и т. д. Поиск в Google _английских существительных, используемых в качестве прилагательных_, кажется, указывает на то, что нет ничего изначально неправильного, хотя не все существительные работают как прилагательные.

Давай попробуем:

_crate mod hello;_ Модуль ящика с именем hello, чувствует себя нормально.
_crate fn world() {}_ Функция ящика с именем world работает нормально.
_crate struct Foo;_ Структура ящика с именем Foo чувствует себя нормально.
_crate enum Bar {}_ Crate enum с именем Bar, все в порядке.
_Черта ящика Баз {}_ Черта ящика по имени Баз, чувствует себя хорошо.

_crate use self::local::Foo;_ Ок, это не работает, использовать crate? Вы можете прочитать это как полезный предмет из ящика с именем Foo. Это ломает шаблон.

Это также может быть неудобным при использовании перед членами структуры и даже больше в сочетании с crate в качестве корня пути.

Хотя ящик не идеален, я не уверен, что «быть существительным» является решающим фактором.

Проблема в том, что это очень редко. Я не знаю ни одного языка программирования, который использует существительные в качестве модификатора типа.

@Центрил

становится проблемой; затем IDE/редактор, который понимает синтаксис Rust, может выделить токены ящика в разных позициях разными цветами. Это должно хорошо прояснить разницу, я думаю.

Лично я нахожу функции различных редакторов приятными, но не думаю, что нам следует разрабатывать язык, исходя из предположения о достаточно продвинутом редакторе. Я чувствовал, что C# был разработан таким образом, и это было основным фактором моего разочарования в этом языке.

@epage Я думаю, что crate в качестве модификатора видимости — хорошая идея, независимо от выделения; Я просто предполагаю, что выделение является дополнительным смягчением. В частности, для любого редактора должно быть довольно тривиально выделять crate:: иначе, чем crate field , потому что первое всегда равно crate + :: , что легко проверить. for во всех случаях, кроме crate ::foo::bar (но это будет довольно редко..).

Как человек, работающий с IDE, я думаю, что такое выделение добавит значительное количество шума к очень небольшому объему информации, что приведет к отрицательному результату. IMO (это очень личное, но основанное на использовании и внедрении мощных IDE) выделение лучше всего работает, когда оно передает семантическую нелокальную информацию (относится ли это использование к переменной, которая была объявлена ​​с помощью mut ) и подчеркивает локальные «стандартные» аспекты кода (поэтому все ключевые слова должны иметь одинаковый стиль).

Мне кажется, что dom (то есть: внутренний) является потенциальным кандидатом.

Он состоит из трех букв (удобно для выравнивания, легко запоминается), это не существительное, и, кроме «объектной модели документа», я не думаю, что к нему прилагается какая-то особая двусмысленность.

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

У кого-нибудь есть мысли по этому поводу?

Один аспект этого, который я видел упомянутым, но не мог найти в резюме (спасибо за это, кстати!), Это то, как ярлык вписывается в существующий синтаксис pub() .

Если pub и <something> (например, crate ) имеют особое значение, это еще больше снижает видимость и, соответственно, знакомство с pub(<something>) . Какое бы решение мы ни выбрали, я думаю, что оно должно поддерживать или заменять существующее оборудование, а не быть еще одним.

Например, если мы используем crate или замену:

  • Следует ли расширить crate , чтобы принять ограничения области видимости (например, crate(<something>) )?
  • Должны ли мы отказаться pub() , чтобы pub имело только одно значение?

Принимая во внимание это и мое понимание цели (прояснить общедоступный API из внутреннего API), я решил воссоздать идею @vitiral о pub(extern) .

  • Подходит для существующего оборудования
  • imo улучшает существующий механизм, делая pub сокращением от pub(<something>) , а не частным случаем
  • Если общедоступный API значительно меньше частного API, значит, мы правильно взвесили синтаксис.
  • Но это может сбить с толку людей с других языков, где public означает, что это может быть в вашем общедоступном API.

RE Влияние на инкапсуляцию

Одним из преимуществ существующей системы pub является инкапсуляция. Простой путь — предоставить API только на один уровень выше. Это упрощает создание общедоступных элементов для частей ящика, но закрытых для всего создания.

Хотя по-прежнему будет pub(super) , наличие ярлыка для pub(crate) будет подталкивать людей к тому, чтобы использовать его чаще, побуждая людей не инкапсулировать свои API.

Я подозреваю, что это не проблема из-за культуры маленьких ящиков.

Но, рассматривая это, это дает мне еще одну итерацию моего комментария выше о pub(extern)

  • pub должен быть ярлыком для pub(super)
  • pub(extern) требуется для вашего общедоступного API.

Ранее я поднимал вопрос о переходе людей с других языков. Это лучше согласуется с ними.

  • Более точно соответствует тому, как public работает на разных языках.
  • Некоторые языки, как правило, имеют отдельный механизм для общедоступного API, поэтому для них это объяснимо.

имо это лучший из всех миров. Так что разорвите его и помогите мне понять, почему нет :)

Я до сих пор ненавижу синтаксис pub(foo) . Гиперболически это выглядит так, как будто он не может решить, является ли это вызовом функции или сочетанием нескольких ключевых слов. Мы не используем let(mut) или for(in) , так что с этим?

@parasyte pub<foo> за победу! В конце концов, разве это не _вид видимости_?

pub<crate> или pub(crate) действительно чувствуют себя лучше.

Некоторые мысли от человека, сменившего лагерь:

Сначала я был очень против crate и думал, что "это портит хороший pub ".

Затем я попробовал его бок о бок в некоторых своих проектах и ​​позволил ему впитаться.

Честно говоря, через несколько дней я больше не мог смотреть на pub(X) , по сравнению с ним он кажется неуклюжим и трудным для чтения.

Сначала я боялся, что может возникнуть (визуальная) двусмысленность; но со мной случилось обратное: если я сейчас увижу crate , я знаю, что это, ну, "вещь из ящика". Будь то импорт модулей или объявление видимости. Что именно в подавляющем большинстве случаев очень понятно из контекста (вроде как двусмысленность в английском).

Я вижу, что в некоторых случаях все еще может быть остаточная «более сложная» (визуальная) двусмысленность, но я бы не хотел обменивать ее на то, что теперь кажется огромным количественным выигрышем в удобочитаемости (например: «строки исходного кода, которые требуют меньше визуальной токенизации/усилий по сравнению со строками исходного кода, которые стали более неоднозначными»).

С этой точки зрения crate - intern (или любая другая асимметрия) также будет казаться шагом назад.

Сказав это, я не знаю о разборе двусмысленности. Если бы мне нужно было выбрать одну из них, я бы предпочел хорошую историю о том, что « crate означает ящик», чем хорошую историю о том, что « crate ::foo::bar просто работает».

Мои два цента в том, что:

  • Я широко использовал crate mod , crate struct , crate fn , ... и считаю его чрезвычайно полезным.
  • Мне все равно, как он называется ( crate , pub(crate) , ...), если он не слишком длинный, потому что я часто его использую.

Если бы это зависело от меня, я бы использовал vis в качестве ключевого слова и тип видимости в качестве модификатора, например, vis(pub) , vis(crate) и т. д., потому что это делает больше мне смысл.

Учитывая, что мы уже застряли с pub в качестве «спецификатора видимости», мне действительно нравится crate . Для меня pub(crate) читается как общедоступный для этого модуля, частный для ящика - я нахожу здесь одновременное использование как общедоступного, так и частного.

Вводить новые ключевые слова и контекстные ключевые слова и т. д., на мой взгляд, не стоит. Обучение тому, что есть две модификации видимости pub и crate , и что одно означает общедоступное, а другое означает личное для ящика, для меня имеет смысл, но, возможно, я просто привык к этому. crate уже за последние две недели.

Тем, кто предполагает, что уже использованное ключевое слово (например, crate ) объединяет значения, я бы сказал, что контекст важнее самого слова. Мозг разбирает все с контекстом (как компилятор разбирает это другой вопрос): это объясняет, почему мы не объединяем семантическое значение for в for x in y и impl X for Y .

В равной степени введение crate в качестве квалификатора видимости, скорее всего, не вызовет путаницы, поскольку его значение в контексте квалификатора члена или функции очевидно, когда он предоставляется с этим дополнительным контекстом. Например, crate fn my_func(); читается не как «это ящик», а как «это функция, видимая ящиком».

Тем не менее, тот факт, что это существительное, непоследователен. Я был бы за создание нового ключевого слова квалификатора видимости для решения этой проблемы.

На самом деле, если есть что-то, что определенно смутит пользователей, так это синтаксис pub(crate) , который интуитивно выглядит как вызов функции и не имеет другого синтаксического эквивалента в другом месте языка. Для меня это похоже на уродливый взлом.

Как человек, который выразил обеспокоенность по поводу использования crate в качестве замены pub(crate) и после прочтения последнего поста @aturon :

Поддержка crate в качестве модификатора видимости (отслеживается здесь 138. Судя по отзывам, эта функция вряд ли будет стабилизирована для Rust 2018 .

Я просто хочу убедиться, что я ясно понимаю, что лично я полностью за замену pub(crate) чем- то (как я думаю , что большинство).

В порядке предпочтения, с тем, что, как мне кажется, будет наиболее легко понять, особенно для тех, кто новичок или не знаком с Rust:

  1. intern (или другое подобное новое ключевое слово)
  2. crate
  3. pub(crate)

Если основная команда считает, что intern или что-то подобное в конечном итоге никогда не будет принято, тогда я откажусь от crate , так как я все еще думаю, что это большое улучшение по сравнению с pub(crate) , поскольку причины , которые @Centril и другие сформулировали.

Поэтому я не стал бы этому препятствовать, если бы гораздо более опытная основная команда считала, что это лучший путь вперед. Удобно просто иметь возможность давать обратную связь, выражать идеи для рассмотрения. 👍 Ржавчина!

@ralfbiedert

Сначала я боялся, что может возникнуть (визуальная) двусмысленность; но со мной случилось обратное: если я сейчас увижу ящик, я знаю, что это, ну, "вещь из ящика". Будь то импорт модулей или объявление видимости. Что именно в подавляющем большинстве случаев очень понятно из контекста (вроде как двусмысленность в английском).

@зестерер

Тем, кто предполагает, что уже использованное ключевое слово (например, ящик) объединяет значения, я бы сказал, что контекст важнее самого слова. Мозг анализирует все с учетом контекста (как это анализирует компилятор — другой вопрос): это объясняет, почему мы не объединяем семантическое значение for in для x в y и impl X для Y.

Я не собираюсь призывать вас двоих лично, но послужу примером людей, которые выступают за изменение после его использования.

Хотя я нахожу это странным, больше всего меня беспокоят не рустообразные.

  • Как это может повлиять на чье-то мнение при оценке ржавчины? Синтаксической причуды одной вещи не должно быть достаточно, чтобы разубедить их, но если вы добавите к этому время жизни и любые другие «странные» вещи, это может обескуражить людей.
  • Как это влияет на людей, изучающих Rust?
  • Как это повлияет на людей, которые не знают Rust, но хотят его модифицировать?

Я был бы рад, если бы мы могли провести исследование юзабилити, чтобы лучше понять, какое влияние оказывают эти опасения.

@epage , полностью согласен, части Rust, ориентированные на пользователя, должны быть протестированы на UX. Однако я думаю, что это то, что происходит прямо сейчас, и мы находимся в процессе обсуждения результатов.

Чтобы добавить к этому, некоторые анекдотические наблюдения от нашей компании:

Я «защитник ржавчины» в нашем отделе, работаю с тремя другими. Все имеют солидный опыт работы с C#, но относительно плохо знакомы с Rust. На днях я перенес наш исследовательский проект на Rust 2018 вместе с " crate -stuff".

Когда мы проходили код, разговоры шли примерно так:

«Итак, вот некоторые другие изменения, которые я сделал: новая система импорта, модификаторы».

"Что это делает?" (указывая на use crate::object и crate x: object )

«Импорт из этого ящика». и «Модификатор видимости».

"А, хорошо. Что-нибудь еще изменилось?"

Конец дискуссии.

Конечно, мы еще немного поболтали о новых функциях и о том, следует ли нам использовать определенные шаблоны; но «учебный аспект» этих двух пунктов сводился к нескольким словам и с тех пор (насколько мне известно) не упоминался.

Если я услышу что-нибудь еще в следующий раз, когда мы поговорим, я обновлю этот комментарий.

@ralfbiedert Спасибо, что поделились этим!

@epage , полностью согласен, части Rust, ориентированные на пользователя, должны быть протестированы на UX. Однако я думаю, что это то, что происходит прямо сейчас, и мы находимся в процессе обсуждения результатов.

Хотя я ценю эти анекдоты UX, особенно с точки зрения обучаемости, я не думаю, что могу квалифицировать этот процесс как UX-тестирование. Мой комментарий относится к более формальному процессу, который может помочь получить более глубокое понимание, отсеять предубеждения и т. д.

Вот несколько мыслей от новичка в Rust. Во-первых, я хочу сказать, что что-то, что действительно кажется разумным и приятным с этим языком, — это подход «неизменяемый по умолчанию, закрытый по умолчанию».

Теперь pub хорош, потому что он прост и ожидаем в современных языках. Я чувствую, что необходимость разучиться этому в контексте Rust и вместо этого повсюду рассыпать другое ключевое слово немного неуклюже. Семантически кажется правильным, что это означает «это кнопка, которая появляется на поле», поле является модулем: видимость «на один уровень выше».

Так что для меня использование crate или другого ключевого слова такого рода вместо pub просто вызывает раздражение: если быть общедоступным не по умолчанию, экспорт из ящика должен быть еще более особенным. . То есть API крейта должен быть обозначен особым образом.

Итак, я полностью согласен с @epage , pub должен остаться прежним, и должна быть введена какая-то pub(extern) . Ключевые слова в скобках действительно кажутся слишком сложными, поэтому, возможно, они заслуживают специального ключевого слова. Ключевое слово crate будет работать в этом смысле, я вижу, что оно означает «это экспортированный член ящика». Или export на самом деле, я не знаю. Хотя, может быть, все, что я хочу сказать, это велосипедный сарай, и все это сводится к тому, что «ключевые слова неверны». Но pub настолько распространен, что не кажется чем-то особенным, поэтому он не должен представлять что-то действительно особенное (API, экспортируемый из корзины).

На этих выходных я смотрел выступление на RustConf, в котором в примерах кода использовалось много pub(crate) , и это действительно заставило меня пожелать старого доброго crate . Я по-прежнему очень поддерживаю первоначальный план.

@стевеклабник

На этих выходных я смотрел выступление на RustConf, в котором в примерах кода использовалось много pub(crate), и это действительно заставило меня пожелать старый добрый ящик. Я по-прежнему очень поддерживаю первоначальный план.

Контекст этого комментария в основном от RustConf или он учитывает эту ветку и предполагает несогласие с ней? Ранее я предоставил альтернативное решение не для pub(crate) , а для требований, определяющих любые изменения pub , и я надеюсь, что оно удовлетворит потребности людей.

Видеть

@superseed

Итак, я полностью согласен с @epage , паб должен остаться прежним и должен быть введен какой-то паб (внешний). Ключевые слова в скобках действительно кажутся слишком сложными, поэтому, возможно, они заслуживают специального ключевого слова. Ключевое слово ящика будет работать в этом смысле, я вижу, что оно означает «это экспортированный член ящика». Или экспортировать на самом деле, я не знаю. Хотя, может быть, все, что я хочу сказать, это велосипедный сарай, и все это сводится к тому, что «ключевые слова неверны». Но pub настолько распространен, что не кажется чем-то особенным, поэтому он не должен представлять что-то действительно особенное (API, экспортируемый из корзины).

RE "Ключевые слова в скобках действительно кажутся неудобными"

Хотя лично я думал, что они хороши, когда я узнал о них (намного лучше, чем все или ничего friend ), меня больше беспокоит то, что мы не создаем параллельный синтаксис, а либо используем то, что у нас есть, либо находим альтернативное решение.

С другой стороны...

RE Или export на самом деле,

Я не думаю, что добавление export противоречит моему предыдущему комментарию, в отличие от crate . В этом контексте export можно рассматривать как нечто отличное от видимости. export означает pub(crate) . Я подозреваю, что это не будет иметь большой проблемы в обучении.

Я могу пойти любым путем в этом расширении моей первоначальной идеи.

@superseed

pub […] видимость "на уровень выше".
Ключевое слово crate будет работать в этом смысле, я вижу, что оно означает «это экспортированный член ящика».

Я думаю, что ваше понимание значения этих двух ключевых слов может быть полной противоположностью тому, что предлагается здесь, а именно, что pub означает общедоступный для всех, а crate означает доступный из одного и того же ящика.

@epage

В случае с pub(crate) он предлагает действительно удобную функцию и на самом деле хорошо читается, но на мой взгляд слишком похож на вызов функции. т.е. без синтаксической подсветки я, вероятно, был бы действительно сбит с толку, а подсветка не нужна для понимания семантики языка.

@SimonSapin

В самом деле, и я понимаю, что именно так это и должно пониматься, но crate — будучи существительным — похоже, объявляет либо ящик (?), либо свойство ящика. Акцент на объявлении, а не на уточнении.

И public / pub — такой вездесущий квалификатор, что (мне!) кажется, что он не должен означать «это экспортировано из ящика». Оно имеет значение «это видно вне того контекста, в котором я нахожусь», как в случае с его использованием для определения видимости члена struct (и поправьте меня, если я ошибаюсь, но я не не думаю, что в этом случае семантика меняется).

А public/pub — такой вездесущий квалификатор, что (мне!) кажется, что он не должен означать «это экспортировано из ящика». Он имеет значение «это видно вне того контекста, в котором я нахожусь», как в случае с его использованием для определения видимости члена структуры (и поправьте меня, если я ошибаюсь, но я не думаю, что семантика меняется в этом случае).

pub всегда означало «это экспортировано из ящика» — это не изменение, это уже так. Тот факт, что многие считают иначе, является причиной того, что уровень видимости pub(crate) вообще повышается.

pub всегда означало "это экспортируется из ящика"

Я думаю, что это понимание также может вызвать некоторую путаницу, потому что это не полная картина. pub действительно означает «Мне все равно, кто за пределами этого модуля получает доступ к этому элементу/полю/методу». Для экспорта из ящика по-прежнему требуется, чтобы путь к элементу также имел те же самые модификаторы pub .

Эта деталь довольно обычна во многих языках. Вот почему я не в восторге от unreachable_pub lint, так как это часть того, что так сильно продвигает эту проблему. Если у меня есть тип, который никогда не экспортируется на верхнем уровне, то изводить меня тем, что я пометил его методы pub , просто похоже на шум.

@rpjohnst Это действительно то, что всегда означало? Разве это не цепочка «видимый из super » из верхней части ящика, из-за которой элемент был экспортирован, а не квалификация самого листового элемента как pub ?

Нет, это не вся история, и разъяснение @seanmonstar намекает на остальное. Самым большим исключением является реэкспорт - вы можете pub use что-то, чьи родительские модули являются частными. Еще более странный пример : вам разрешено использовать элемент pub в общедоступном интерфейсе, даже если его родительские модули являются частными.

И идя в другом направлении, pub(crate) и меньшие видимости нельзя обойти таким же образом - вы не можете pub use то, что еще не pub , даже если pub use сам по себе не виден снаружи контейнера.

Таким образом, собственная видимость элемента напрямую связана не с его видимостью для super , а с его «верхним пределом» видимости в любом месте .

Ооо хорошо, спасибо за разъяснение! Я имел в виду гораздо более наивную модель. Это имеет больше смысла в отношении предыдущих комментариев о «текущем значении паба».

Сегодня мы кратко обсудили на встрече @rust-lang/lang:

  • Многие из нас положительно относятся к этому, но остаются сомнения по поводу выбора ключевого слова и того, может ли оно создать путаницу в сочетании с путями crate::foo::bar
  • Тем не менее, стоит отметить, что мы должны решить, каким образом разрешить struct Foo ( crate :: foo :: Bar ) -- это закрытое поле типа (crate::foo::Bar) или это поле crate типа ::foo::Bar ?

    • Я, честно говоря, не уверен, что мы анализируем это, как сегодня

Ответ: разбираем как путь ( игровая площадка ).

Это кажется... вероятно, мне подходит, потому что я думаю, что пути ::foo::bar будут становиться все более редкими.

Многие из нас положительно относятся к этому, но остаются сомнения по поводу выбора ключевого слова и того, может ли оно создать путаницу в сочетании с путями crate::foo::bar.

@nikomatsakis , есть записи о встречах или краткое изложение, чтобы мы могли наверстать упущенное? В этой ветке я не видел ни обсуждения хотя бы одной из моих проблем[0], ни большого обсуждения встречных предложений. Может быть, [0] и некоторые другие обсуждались в различных темах, посвященных внутренним вопросам, но это слишком много, чтобы копаться в них.

[0] создание синтаксиса параллельной видимости, отодвигающего pub(...) в неизвестность с ощущением, что мы должны либо удалить, либо принять pub(...)

@epage

@nikomatsakis , есть записи о встречах или краткое изложение, чтобы мы могли наверстать упущенное?

Нет простите; Мы не обсуждали это очень долго (максимум несколько минут) и не записывали никаких заметок по этому поводу.

@eddyb кратко упомянул my как более короткий и эргономичный модификатор видимости.

Кажется, я сказал mine , но my еще короче, прелесть!
(Для протокола, я полушутил на встрече)

РЕДАКТИРОВАТЬ : если my является локальным ящиком, можем ли мы заменить pub на our ? например:

our struct Foo(my FooImpl);

(Для протокола, я полушутил на встрече)
если my является локальным, можем ли мы заменить pub на our ?

Perl: превращая шутки в реальность.
https://perldoc.perl.org/functions/my.html
https://perldoc.perl.org/functions/our.html

my хорош (и встречался раньше), дело в том, что это не яснее, чем local , internal или что-то еще, по отношению к чему (или в свой случай, чей ), в чем и вся проблема.

Неловкая ситуация, в которой мы находимся, заключается в том, что мы хотим иметь три уровня конфиденциальности — «полностью общедоступный», «полностью частный» и «где-то посередине» (т. е. уровень ящика) — и из-за ограничений обратной совместимости мы вы застряли с первым из них обязательно pub , вторым является неявное значение по умолчанию, и вам нужно придумать что-то новое для третьего. И в английском языке не так много слов, которые точно обозначают «ни полностью глобальное, ни полностью локальное, но где-то посередине».

И ключевое слово crateэто то, что удовлетворяет этому, потому что прямо в названии указано, какова фактическая область действия — это ящик. Но (прежде чем вы начнете восклицать «Я так и знал !»), цена этого в том, что уже не очевидно, что это модификатор видимости . «Паб» — это сокращение от «общественного», это можно понять интуитивно. Но ни в одном другом языке нет понятия «ящик» (с таким названием); чтобы иметь хоть какую-то надежду понять смысл crate struct , нужно сначала узнать об этом. 1 Это требует от нас дальнейшего изъятия из «бюджета странности языка», и мнения могут расходиться по поводу того, остается ли баланс положительным.

Между тем, pub(crate) решает обе проблемы — он говорит вам, что это модификатор видимости, и он сообщает вам, что такое область действия — но взамен он длинный и неудобный.

Так что это в основном форма затруднительного положения.

1 (Кто-то выше описал взаимодействие, которое выглядело так: «Они спросили, что означает crate , я сказал им, что это модификатор видимости, и на этом все закончилось». Проблемная и, возможно, более распространенная ситуация возникает, когда рядом с вами случайно не сидит рустообразный.)

FWIW, я был бы полностью согласен с our или my для местных предметов.
Ключевое слово our даже состоит из трех букв и прекрасно сочетается с pub ~и с Perl~.
Проблема в том, что они звучат слишком неформально (для носителей английского языка?)?

Как люди относятся к intern ? Это один символ длиннее, чем crate , но в остальном я думаю, что он будет более интуитивно понятным, чем crate для людей, плохо знакомых с Rust, и имеет хорошую симметрию с ключевым словом extern .

IMO our и my имеют ту же слабость, что и local и internal : они не очень хорошо понимают свою область применения. local , в частности, довольно сбивает с толку, так как область действия будет радикально отличаться от локальных переменных, где локальная означает закрытую область действия, которая для элемента будет модулем, а не ящиком. Я нахожу internal немного неконкретным. Внутреннее чему? Модуль? Тип? Ящик? Это может быть очевидно для тех, кто пришел из языков, где он используется, но не обязательно будет для других. our и my еще более расплывчаты. Напротив, crate очень четко указывает на объем.

Что касается pub(extern) , у меня действительно есть вопрос. Есть ли смысл иметь extern "C" fn foo() {} без pub впереди? Потому что если бы это было не так, мы могли бы повторно использовать extern fn foo() {} и для наших обычных функций Rust, отличных от "C". Я думал, что мы могли бы унифицировать это и не оставлять внешний синтаксис специальным для FFI. Это будет означать, что extern теперь обесценивается до pub(extern) , pub остается таким же, как и сегодня, но принимает необязательную строку ABI, если элемент ее поддерживает, и lint для pub элементов экспортируется без pub(extern) или 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!");
}

Я не видел, чтобы это упоминалось в темах, которые я читал, поэтому извиняюсь, если это обсуждалось раньше!

Есть ли смысл иметь extern "C" fn foo() {} без паба впереди?

Да, иногда вы хотите использовать, например, только foo в качестве указателя функции. И на самом деле синтаксис extern fn foo() {} не может быть повторно использован для этого в любом случае, потому что extern без "C" по умолчанию соответствует C ABI, и это считается идиоматичным, по крайней мере, некоторыми.

Вот предложение, которое появилось давным-давно — может быть, мы можем дать ему еще один шанс сейчас, когда некоторые аспекты новой модульной системы выкристаллизовались?

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

Я считаю, что это имеет смысл, если подумать о:

  • «общественность» как «общественность для мира»
  • "частное" как "частное в ящике"
  • «без модификатора видимости» как «вообще не видно»

У некоторых людей была рефлекторная реакция на то, что priv не является самым ограничительным, но я хочу сделать два замечания по этому поводу:

  1. В Rust модули используются для организации вещей в пространствах имен, а ящики используются для определения интерфейсов. Итак, если крейт — это «единица API», то для модификаторов видимости имеет смысл говорить в первую очередь о крейтах.

  2. Я думаю, что Java допустил ошибку private , что означает «приватный для класса», а модификатор видимости не означает «видимый внутри пакета». Для меня более разумно, чтобы модификатор не был самым ограничивающим (т. е. по умолчанию).

@stjepang Я бы сказал, что в большинстве других случаев «частное» будет иметь более ограничительный оттенок, чем неизмененное состояние. Спектр частный-стандартный-общедоступный в общем смысле аналогичен защищенному-доступному-рекламируемому.

Частный клуб более эксклюзивен, чем клуб.
Частный акт подразумевает, что были предприняты некоторые усилия, чтобы скрыться от всеобщего обозрения.
Частная мысль должна быть избыточной концепцией, учитывая, что эволюция не смогла наделить нас телепатией, но большинство людей признают, что это означает мысль, предназначенную для того, чтобы ею не делились.

Как неопытный человек, изучающий языки, я бы также предположил, что дополнительное ключевое слово является меньшей когнитивной нагрузкой, чем одно ключевое слово с несколькими контекстно-зависимыми значениями. См. Костелло, Л. и Эббот, Б. «Кто первый», 1938 г.

Я чувствую, что my и our будут иметь коннотации, которые нам не нужны, не говоря уже о сложности резервирования их в качестве ключевых слов. Это забавная шутка, но я не думаю, что нам следует идти по этому пути.

Я искренне чувствую, что люди узнают, что означает видимость crate . Я думаю, что большая проблема связана с кодом, который становится трудно читать или неоднозначно анализировать:

crate struct S(crate crate::Foo);

crate struct S(crate ::Foo);

Я лично не вижу в этом ничего особенного, но здесь они определенно вызывают озабоченность.

В языке Scala есть аналог pub(path) , который равен private[path] и действует почти так же. Он читается немного по-другому, говоря: «Этот элемент является частным, его могут просматривать только люди в пределах $path». Но для того, чтобы сделать что-то приватным в Scala, требуется аннотация, так как по умолчанию она общедоступна, чего нельзя сказать о Rust.

Мне приходит в голову, что концепция C++ friend s также похожа на pub(path) , как еще одна точка прецедента.

В конечном счете вопросы таковы:

  1. ключевое слово crate используется как для импорта относительных путей, так и в качестве модификатора видимости,
  2. ключевое слово crate предотвращает унифицированный синтаксис модификатора видимости, такой как pub(...) ,
  3. некоторым не нравится синтаксис pub(crate) (слишком длинный, выглядит как вызов функции).

После 5 минут действительно глубоких размышлений я придумал следующее... :P

Специальный синтаксис для модификаторов видимости

_(на примере @ )_

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

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

Я лично нахожу это довольно уродливым, и я бы не хотел набирать @crate или pub(crate) .

Отличительные ключевые слова модификаторов видимости

Поскольку уже есть голые pub и extern , я думаю, что ключевое слово crate вполне подходит (неудивительно, если исходить из языков с обычными public , protected , private ключевые слова).

crate struct Foo;

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

Но, как я уже сказал, это не очень хорошо работает с префиксом импорта crate , и мне начинает казаться, что мы получили это задом наперед. Я чувствую, что реальная проблема заключается в изменении ясности пути, например, без подсветки синтаксиса:

use crate::utils;

похоже, что crate не имеет особого значения.

Вдохновленный синтаксисом декларативных макросов, вместо того, чтобы искать какой-то унифицированный синтаксис для модификаторов видимости, я бы предпочел следующее:

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 и crate для импорта путей требуют префикса, например, $crate , из чего совершенно ясно, что они являются специальными и похоже на переменные)

Запутанный пример:

crate struct Foo(crate crate::Bar);

становится:

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

Похоже, есть проблема с отслеживанием дубликатов: https://github.com/rust-lang/rust/issues/45388.
Закрытие этого в пользу этого.

Есть ли причина, по которой реализация rustc тестирует эту функцию? Каждый экземпляр crate fn можно заменить на pub(crate) fn и перестать полагаться на нестабильную функцию AFAICT.

Я не вижу веских причин, почему мы должны это делать. И Clippy, и rustc постоянно используют нестабильные функции, и они должны это делать, потому что это позволяет нам более тщательно их тестировать как с точки зрения обнаружения ошибок в реализации, так и потому, что мы можем почувствовать, как их использовать.

В этом случае использование crate в качестве модификатора видимости в Clippy и rustc, на мой взгляд, показывает, что он читается лучше, чем pub(crate) , и что большинство проблем, упомянутых в этой проблеме отслеживания, не являются -проблемы на практике. Я думаю https://github.com/rust-lang/rust/issues/53120#issuecomment -413466129, https://github.com/rust-lang/rust/issues/53120#issuecomment -414392549 и https:/ /github.com/rust-lang/rust/issues/53120#issuecomment -413498376 также предполагает, что crate в качестве модификатора видимости хорошо работает и снаружи.

Так как это хорошо работает на практике, так как многие из нас в языковой группе положительно относятся к этому , и поскольку это было принято RFC , я думаю, что мы должны рассмотреть возможность стабилизации crate в качестве модификатора видимости после рассмотрения того, как мы должны анализировать struct Foo ( crate :: foo :: Bar ) ( в настоящее время как путь, и, вероятно, это правильно ).

FWIW, я использую эту функцию в Cargo-n64, и это очень приятно!

Я постоянно использую crate в rustc, потому что он короткий и не имеет круглых скобок, таких как pub(crate) .
Хотя мне все равно не нравится, как это читается.
Он также не имеет 3 букв, поэтому форматирование меняется вместе с изменениями pub <-> crate .
Мне все еще нравится our без иронии.

@petrochenkov Я понимаю, что вы написали, так это то, что вы предпочитаете crate pub(crate) , но также хотели бы что-то лучше, чем crate . Это точная оценка?

FWIW, я все еще думаю, что intern — хороший вариант.

  • Без скобок
  • Короче, чем pub(crate) (хотя один символ длиннее, чем crate )
  • Читается лучше (IMO), чем crate (который используется для других вещей, таких как пути, например, crate::foo::bar )
  • Имеет хорошую симметрию с существующими extern
  • Знакомо, так как в других языках используется что-то подобное ( internal ). Котлин, С# и т.д.

При этом я также согласен с тем, что pub(crate) следует чем- то заменить.

хорошо, тогда решено - три буквы хорошо, и "стажер" хорошо, так что... int . ;)

Можем ли мы получить корпию для дела crate ::T (с пробелом)?

@Centril Некоторые из нас только что обсуждали дальнейшие действия на #rocket. Основываясь на вашем недавнем комментарии, есть ли возможность предложить FCP в ближайшем будущем?

@jhpratt Я собирался написать рецензию и в конечном итоге предложить ее, но я был занят другими вещами. Постараюсь найти время в ближайшее время.

Итак, я просто просматривал выпуски, искал что-то о макросах и нашел это.

Теперь, когда у нас уже давно есть pub(crate) в стабильной версии, интересно, не следует ли закрыть эту проблему?

Интересно, что это только что всплыло на недавнем собрании команды разработчиков, где обсуждалось это как возможная проблема, которую мы хотели бы возродить.

Говоря лично, я определенно скучаю по возможности писать crate fn и crate foo: T в полях и тому подобное. Это небольшое синтаксическое отличие от pub(crate) , но я считаю, что это делает код более читабельным, особенно в структурах с большим количеством общедоступных полей. Я также считаю, что это способствует разумно полезной, упрощенной «модели конфиденциальности» —

  • структуры, поля либо локальны для модуля (очень узкое рассуждение)
  • или они используются где-то в текущем крейте ( crate , нужно копировать)
  • или они общедоступны для всего мира ( pub )

На мой взгляд, между этим ключевым словом и изменениями, предусмотренными в https://github.com/rust-lang/rust/issues/48054 , есть некоторое пересечение, и я бы предпочел, чтобы мы приняли их вместе. Я забыл подробности, но помню, что были ошибки, которые можно было бы получить, пытаясь применить вышеуказанную модель на практике.

Я думаю, что первым шагом к этому было бы то, что кто-то попытался бы написать статью, задокументировав историю и убедившись, что мы выдвинули на первый план все проблемы, которые были подняты.

Одна конкретная проблема, которую я помню, — это синтаксическая двусмысленность

struct Foo(crate ::x)

Сегодня это принято, и crate ::x анализируется как путь crate::x , но, вероятно, пользователь имел в виду, что crate служит модификатором видимости с ::x в качестве пути. .

Я был бы склонен повторно ввести модификатор crate и сохранить синтаксический анализ приведенного выше случая таким же, как сегодня. Начиная с Rust 2018, пути ::foo в значительной степени устарели — они все еще существуют и могут быть полезны в определенных конкретных контекстах, таких как макросы, но в большинстве случаев мы теперь поощряем абсолютные пути, которые выглядят как crate_name::b , где crate_name может быть ключевым словом crate или именем другого ящика. Так что вполне вероятно, что crate::x (игнорируя пробелы) на самом деле имелось в виду как путь, и, следовательно, текущий синтаксический анализ правильный.

Если мы хотим устранить потенциальную путаницу пользователей, то я думаю, что lint, чувствительный к пробелам, является достаточно хорошей идеей. Другими словами, struct Foo(crate ::x) выдаст предупреждение, а struct Foo(crate::x) — нет, хотя оба они приняты и эквивалентны.

Лично я больше предпочитаю унифицированный синтаксис и простой парсер lookahead(1); Кроме того, ящик есть ящик, и существует crates.io , и все эти вещи не имеют ничего общего с видимостью _непосредственно_ — только в контексте pub(_) .

Но хорошо, что я знаю? Это просто еще одна точка зрения. У вас, ребята, несомненно, больше опыта и более ценное мнение.

@nikomatsakis Любопытно, есть ли у вас какие-либо мысли о intern для этого варианта использования (или на данный момент резервирование нового ключевого слова выходит за рамки?).

По прошествии пары лет мое мнение осталось прежним: оптимизируйте для удобочитаемости . Я обнаружил, что читаю код гораздо больше, чем пишу его. И так, моё мнение, мне понятнее читать pub(scope) , что может быть pub , pub(crate) , pub(super) , pub(in proto::h1) .


Тем не менее, я не думаю, что мы действительно добавляем что-то новое в разговор с этими мнениями, я уверен, что мы сказали все это в предыдущих комментариях. Должно ли решение основываться на чем-то новом? Или, другими словами, как мы решаем, что теперь решение о принятии этого синтаксиса должно быть «да», когда оно было «нет», или отложить пару лет назад?

Я также считаю, что это способствует разумно полезной, упрощенной «модели конфиденциальности» —

  • структуры, поля либо локальны для модуля (очень узкое рассуждение)
  • или они используются где-то в текущем крейте ( crate , нужно копировать)
  • или они общедоступны для всего мира ( pub )

Я не могу понять преимущества этого упрощения и того, как оно стоит потери в выразительной силе. Что бы это ни стоило, я часто делаю элементы общедоступными для их родительских модулей (чтобы родственные модули могли их использовать), но не для всего ящика. Публично для прародительского модуля в меньшей степени, но все же иногда.

Я чувствую, что отказ pub(super) будет значительной потерей.


Отдельно я не в восторге от использования существительного crate в качестве квалификатора, который модифицирует элемент, который может существовать независимо. Для сравнения: pub(lic), unsafe и const(ant) прилагательные. Существительные, уже используемые в качестве ключевых слов в определениях элементов, не являются квалификаторами, а указывают на характер этого элемента: функция, черта, модуль, …

Ящики — это уже концепция, с которой мы имеем дело, но в этом предложении определение предмета, начинающееся с crate , не определяет новый ящик.

Немного новой информации:

rust-analyzer обеспечивает завершение и помогает добавлять pub(crate) , что (субъективно) делает ввод текста менее раздражающим при трех нажатиях клавиш.

Я согласен, что здесь добавляется мало новой информации. Я думаю, что хорошим следующим шагом, если мы хотим отстаивать предложение, было бы вернуться назад, обобщить нерешенные проблемы и представить его команде lang, чтобы попытаться принять окончательное решение. Я, конечно, предпочел бы либо принять, либо отклонить это предложение, я устал от того, что оно висит в подвешенном состоянии.

Быстро просмотрев весь этот выпуск, я думаю, что недавний комментарий @nikomatsakis довольно хорошо подводит итог. Помимо нескольких избранных людей, которые все еще поддерживают такие вещи, как intern , crate кажется наиболее логичным (и был принят в RFC 2126 ). Единственная действительно нерешенная проблема заключается в том, как анализировать fn foo(crate ::bar) .

Наиболее логичным местом для начала кажется предупредительный по умолчанию lint, чувствительный к пробелам. crate ::bar в настоящее время анализируется как путь и должен оставаться таковым как в Rust 2015, так и в 2018. Однако я полагаю, что это будет кандидат на критическое изменение в редакции.

Случай crate ::bar совершенно не важен на практике и уже ведет себя согласованно с остальной частью языка. Это неизменно было отвлекающим маневром обсуждения, пожалуйста, не заостряйте на этом внимание.

Я, конечно, предпочел бы либо принять, либо отклонить это предложение, я устал от того, что оно висит в подвешенном состоянии.

Думаю, я бы проголосовал за отказ.
Я постоянно использую crate вместо pub(crate) в rustc, и, несмотря на то, что он короче, в большинстве случаев он выглядит неуместно, особенно в полях или импорте, и выбирая между crate и pub(crate) похоже на выбор из двух зол, при этом не зная, какое из них меньшее.

Да. Что еще более важно, так это то, что @SimonSapin упомянул, что crate bar действительно не определяет новый ящик, несмотря на то, что он читается как если бы это было так.

@petrochenkov Вы не думаете, что ворс имеет смысл? Лично, если бы я увидел crate ::bar , не видя этого обсуждения, я бы ожидал, что он будет вести себя как pub(crate) ::bar . Я думаю, что разрешение пробелов в путях _вообще_ сбивает с толку.

@jhpratt Было бы трудно запретить пробелы между сегментами пути из-за характера работы синтаксических анализаторов с токенами. Также это сломало бы безумное количество инструментов, таких как quote!, syn и многие другие.

Думаю, я бы тоже поддержал закрытие этого. Я видел достаточно путаницы, выраженной в отношении значения этой конструкции, и я не думаю, что выигрыш в краткости стоит потенциальной потери удобочитаемости.

Это может лучше соответствовать «большой» (но закрытой) проблеме отслеживания № 44660, но также напрямую связано с модификаторами видимости и не подходит к другим подзадачам № 44660:

В какой-то момент я помню, как кто-то предположил, что pub(path) теперь может быть законным, заменив форму pub(in path) и включив в нее pub(crate) и pub(super) . Это кажется хорошим упрощением pub(...) , хотя и в другом направлении, чем crate , которое мы также могли бы рассмотреть.

Редактировать: на самом деле не уверен, что это работает... struct S(pub(path) Type) неоднозначно (для синтаксического анализа в стиле LL) с такими вещами, как struct S(pub (Type,)) .

Так что я думал об этом в течение последних нескольких месяцев. Я думаю, что пришел к "закрытому" положению. Я думаю, что краткое изложение моей позиции выглядит следующим образом:

  • Идея «трех уровней видимости» (модуль, ящик, мир) относительно проста и привлекательна, но упускает из виду типичные случаи из реальной жизни. pub(super) , в частности, я нахожу очень распространенным на практике, хотя редко требуется более одного уровня (например, pub(crate::foo) ). Например, я часто хочу иметь модули, которые имеют подмодули, и использование видимости ящика для этих деталей не может передать предполагаемый уровень конфиденциальности.
  • Модель «локальная для какой-либо части ящика или общедоступная для всего мира» также концептуально проста и элегантна и охватывает все эти варианты использования.
  • pub(crate) fn , хотя и значительно менее лаконичный, чем просто crate fn , не так уж и плох. Забавно, что pub(crate) расширяется до pub(crate::foo) , что покрывает другой вариант использования, который я иногда получаю (например, «большие» модули в ящике), но это настолько многословно, что я подозреваю, что это будет редко, если вообще когда-либо будет использоваться, и вполне вероятно, что эти большие модули в любом случае лучше разбить на подкрейты...
  • Я думаю, что самые большие эргономические препятствия вокруг «смешанных уровней конфиденциальности» возникли из-за ошибок и ошибок, связанных с тем, что мы пытались гарантировать, что (например) все типы, которые появляются в pub(x) fn , имели подходящую конфиденциальность. Мы изменили эти правила, и я просто чувствую, что больше не сталкиваюсь с этими раздражающими факторами, и если таких раздражающих факторов станет больше, я думаю, мы сможем решить и их.

    • Например, можно написать pub в полях, что означает «такой же общедоступный, как и сама структура», и я думаю, что это прекрасно работает.

И, конечно же, тот факт, что если мы не добавим crate fn сейчас, не означает, что мы не сможем добавить его позже. В частности, я думаю, что модель «трех уровней конфиденциальности» работала бы лучше, если бы у нас был какой-то способ создавать «легкие встроенные ящики» внутри другого ящика. т. е. если бы вместо субмодуля внутри крейта я мог объявить приватный крейт со всеми вытекающими последствиями (в первую очередь, возможно, DAG-подобное отношение к другим вещам). Я не уверен, что легкие, встроенные ящики действительно будут работать, но они могут покрыть и заменить множество вариантов использования, подобных pub(super) . Если бы я когда-нибудь исследовал это, я бы подумал о повторном открытии обсуждения вокруг crate fn , так как это может стать значительно более полезным/распространенным.

Короче говоря, я бы высказался за удаление уровня видимости crate из компилятора и удаление ворот функций.

Я просто хотел проверить, когда эта функция может быть стабилизирована, и я удивлен и разочарован тем, что есть планы по ее удалению. Я использую его изо дня в день с тех пор, как он был добавлен, и меня почти не беспокоят какие-либо из проблем, обсуждавшихся выше. Например, я до сих пор не написал ничего похожего crate ::path и, вероятно, никогда не напишу, так как никогда не касался синтаксиса ::path .

Конечно, есть возможности для улучшения. Ключевое слово можно было бы выбрать лучше, pub(super) по-прежнему неудобно, и неприятно получать предупреждения о мертвом коде повсюду, когда я использую видимость на уровне ящика для вспомогательных методов. Тем не менее, как пользователь, я бы предпочел, чтобы эта функция оставалась (закрытой) до тех пор, пока не будет найдено лучшее решение. Синтаксис pub(crate) немного раздражает и немного отбивает желание разбивать большие модули на более мелкие и компактные.

думаю, что самые большие эргономические препятствия вокруг «смешанных уровней конфиденциальности» возникли из-за ошибок и ошибок, связанных с тем, что мы пытались гарантировать, что (например) все типы, которые появляются в pub(x)fn, имели подходящую конфиденциальность.

Означает ли это, что мы также не включаем lint «unreachable pub» ( mod private { pub fn f() {} } )?

Хех, у меня были другие мысли, когда я читал различные коды rustc и видел, как crate используется, и я думаю, что все эти случаи были pub(crate) … вероятно, стоило бы сделать переход экспериментально, просто чтобы посмотреть, как разница заставляет меня чувствовать. Я помню, как мне было грустно из-за мела, когда мы перенесли его из ночного в конюшню, хотя я думаю, что теперь, когда я к нему привык, это меня не так сильно беспокоило.

@matklad Надеюсь, нет, я думаю, что ворс тоже очень важен. Честно говоря, я не совсем понимаю, почему я не сталкивался с такими ошибками и неприятностями, как раньше. Возможно, в последнее время я просто недостаточно пишу код на Rust! Я точно помню, что раньше у меня были эти надоедливые циклы, когда казалось, что я не могу удовлетворить компилятор, кроме как делать больше вещей pub , чем мне хотелось.

Как насчет сохранения pub(crate) и добавления псевдонима pubc ? Это читается очень похоже, не нарушает текущий код и устраняет необходимость вводить круглые скобки (что делает его немного быстрее).
Это также позволит pubs для видимости в родительском элементе.

Короче говоря, я бы высказался за удаление уровня видимости crate из компилятора и за удаление гейта функций.

Я считаю, что pub(crate) немного раздражает и шумит, когда я читаю код. Вместо этого было бы неплохо иметь модификатор видимости crate .

И, конечно же, тот факт, что если мы не добавим crate fn сейчас, не означает, что мы не сможем добавить его позже. В частности, я думаю, что модель «трех уровней конфиденциальности» работала бы лучше, если бы у нас был какой-то способ создавать «легкие встроенные ящики» внутри другого ящика. т. е. если бы вместо подмодуля внутри крейта я мог бы объявить приватный _crate_ со всеми вытекающими последствиями (в первую очередь, возможно, DAG-подобное отношение к другим вещам). Я не уверен, что легкие, встроенные ящики действительно будут работать, но они могут покрыть и заменить множество вариантов использования, подобных pub(super) . Если бы я когда-нибудь исследовал это, я бы подумал о повторном открытии обсуждения crate fn , так как это может стать значительно более полезным/распространенным.

Мне определенно понравились бы эти "легкие" ящики, о которых вы говорите! Это было бы намного приятнее, чем сразу переходить к рабочим пространствам, которые довольно тяжелые.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги