Как я могу использовать признак из крейта транзитивных зависимостей в своем приложении?
Вот минимальный наглядный пример проблемы, с которой я столкнулся:
В 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, и это несмотря на то, что они пишутся одинаково. , это отдельные и несвязанные характеристики, и поэтому на них нельзя ссылаться как на взаимозаменяемые.
Итак, у меня есть несколько вопросов:
Rng, которая работает для MT19937, в моем приложении? Я не думаю, что смогу понизить свою зависимость от rand до 0.4.6 в Cargo.toml, потому что мне нужно использовать rand 0.8.5 elsewere в своем приложении.mersenne_twister плохой практикой из-за отсутствия реэкспорта Rng?
Я не думаю, что смогу понизить свою зависимость от 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, такие как дистрибутивы.
Также отличный звонок crate mt19937, это точно решает мою проблему. Хотя мне трудно его обнаружить: я искал Mersenne Twister на crates.io, но он не нашелся, и если бы вы мне о нем не сказали, я, вероятно, никогда бы его не обнаружил. Я надеюсь, что когда-нибудь crates.io сможет лучше справляться с обнаружением ящиков.
@ RBF06 Я бы сказал, что наиболее каноничным было бы отправить PR на зависимость, что гарантирует выгоду всем, но вышеупомянутое решение гарантированно сработает немедленно. Вы также можете скопировать код напрямую в свой проект (если позволяет лицензия) и исправить его там, или, если вы не планируете публиковать свой крейт на crates.io, вы можете использовать [патч].
Вы хотите сказать, что в целом, если общедоступный ящик A реализует признак общедоступного ящика B в общедоступном типе, то ящик A должен публиковать новую версию без обратной совместимости каждый раз, когда это делает B?
В значительной степени, хотя в этом случае это было бы изменением, чтобы оно также зависело от rand_core, который, оглядываясь назад, фактически появился после последней версии mersenne_twister. Я подозреваю, что причина того, что mersenne_twister не был обновлен, заключается в том, что существует mt19937. Cargo позволяет легко зависеть от старых версий, поэтому публикация обратно несовместимой версии должна быть полностью выгодна, когда альтернатива не публикует ничего.
Моей первой мыслью было добавление нескольких версий одного и того же ящика в качестве прямых зависимостей посредством переименования, но мне это показалось очень неприятным, поэтому я хотел этого избежать. Является ли это каноническим методом решения проблемы зависимостей?