Как я могу использовать черту из транзитивной зависимости в Rust?

Как я могу использовать признак из крейта транзитивных зависимостей в своем приложении?

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

В Cargo.toml у меня есть:

[dependencies]
mersenne_twister = "1.1.1"
rand = "0.8.5"

Мой ящик зависит от rand ^0.8.5 и mersenne_twister ^1.1.1, который сам зависит от rand >=0.3, <0.5:

my-crate ---> rand 0.8.5
         |
         |
         ---> mersenne_twister 1.1.1  ----> rand >= 0.3, < 0.5

В своем приложении я хотел бы использовать реализацию типажа rand::Rng для mersenne_twister::MT19937. Но когда я пытаюсь реализовать эту черту, она, по-видимому, не распознается:

use mersenne_twister::MT19937;
use rand::Rng;

fn main() {
    let mut rng = MT19937::new_unseeded();
    let mut buffer = vec![0; 0xFFFF];

    // error[E0599]: no method named `fill_bytes` found for struct `MT19937` in the current scope
    rng.fill_bytes(&mut buffer);
}

Я предполагаю, что признак Rng, импортированный use rand::Rng;, — это признак из rand 0.8.5 , а не признак из rand 0.4.6, который на самом деле реализован для MT19937, и это несмотря на то, что они пишутся одинаково. , это отдельные и несвязанные характеристики, и поэтому на них нельзя ссылаться как на взаимозаменяемые.


Итак, у меня есть несколько вопросов:

  1. Как я могу использовать черту Rng, которая работает для MT19937, в моем приложении? Я не думаю, что смогу понизить свою зависимость от rand до 0.4.6 в Cargo.toml, потому что мне нужно использовать rand 0.8.5 elsewere в своем приложении.
  2. В общем, как следует использовать черты, определенные в транзитивных зависимостях?
  3. Является ли дизайн API mersenne_twister плохой практикой из-за отсутствия реэкспорта Rng?
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
4
0
108
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не думаю, что смогу понизить свою зависимость от rand до 0.4.6 в Cargo.toml, потому что в противном случае мне нужно использовать rand 0.8.5 в моем приложении.

Вы можете использовать оба, переименовав одну или обе версии.

[dependencies]
rand4 = { package = "rand", version = "0.4.6" }
rand8 = { package = "rand", version = "0.8.5" }

Затем вы можете ссылаться на rand4::Rng или rand8::Rng в своем коде по мере необходимости.

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

Является ли дизайн API mersenne_twister плохой практикой из-за отсутствия реэкспорта Rng?

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

Ответ принят как подходящий

Вы можете добавить в Cargo.toml несколько несовместимых версий зависимости, переименовав одну из них.

[dependencies]
mersenne_twister = "1.1.1"
rand = "0.8.5"
old_rand = { package = "rand", version = "0.4.6" }

Но для этой ситуации уже есть лучшее решение: использовать крейт MT19937, который зависит от последней версии rand_core. Реализации RNG должны зависеть от rand_core, а не от rand, поскольку все, что им нужно, это черта Rng, а не какие-либо дополнения в rand, такие как дистрибутивы.

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

RBF06 23.02.2024 02:31

Также отличный звонок crate mt19937, это точно решает мою проблему. Хотя мне трудно его обнаружить: я искал Mersenne Twister на crates.io, но он не нашелся, и если бы вы мне о нем не сказали, я, вероятно, никогда бы его не обнаружил. Я надеюсь, что когда-нибудь crates.io сможет лучше справляться с обнаружением ящиков.

RBF06 23.02.2024 02:56

@ RBF06 Я бы сказал, что наиболее каноничным было бы отправить PR на зависимость, что гарантирует выгоду всем, но вышеупомянутое решение гарантированно сработает немедленно. Вы также можете скопировать код напрямую в свой проект (если позволяет лицензия) и исправить его там, или, если вы не планируете публиковать свой крейт на crates.io, вы можете использовать [патч].

drewtato 23.02.2024 03:44

Вы хотите сказать, что в целом, если общедоступный ящик A реализует признак общедоступного ящика B в общедоступном типе, то ящик A должен публиковать новую версию без обратной совместимости каждый раз, когда это делает B?

RBF06 24.02.2024 21:19

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

drewtato 24.02.2024 22:58

Другие вопросы по теме

Добавьте IoC в файл Program.cs в .NET 8 из контейнера зависимостей
Проблема при создании библиотеки Arduino с зависимостями
Pusher\Pusher::__construct(): Аргумент №1 ($auth_key) должен иметь строковый тип, с заданным нулевым значением,
Конфликт зависимостей с TOCropViewController в проекте React Native
Циклическая зависимость C++ с защитой заголовков и упреждающими объявлениями
Управление зависимостями Gradle из пружины.Управление зависимостями не работает
Как установить внешние зависимости Clojure локально в проекте?
Docker строит точно такие же требования. txt и Dockerfile, 4 недели назад успешно, но в настоящее время не удалось
Docker строит точно такие же требования. txt и Dockerfile, 4 недели назад успешно, но в настоящее время не удалось
Maven снова загружает все зависимости, потому что они были «кэшированы из идентификатора удаленного репозитория, который недоступен в текущем контексте сборки»