如何防止 Cargo 将相同的依赖项与不同的功能合并?

How can I prevent Cargo from merging the same dependency with different features?

弄清楚cargo build of the same code: spurious compile time errors?后,我想知道如何防止这样的问题:

$ cargo new feature_merge
$ cargo add nmea
$ cargo check > /dev/null 2>&1 && echo "success"
success
$ cargo add cexpr
$ cargo check > /dev/null 2>&1 || echo "failed"
failed
$ cargo rm cexpr && cargo check > /dev/null 2>&1 && echo "success"
success

我remove/add没有任何代码修改的依赖项,这会影响构建结果。

问题的根源,as I described, is that cexpr 取决于这样的 nom:

nom = {version = "^3", features = ["verbose-errors"] }

nmea 是这样描述依赖关系的:

nom = "3.1.0"

只有 nmea 作为依赖项,Cargo 构建具有一组功能的 nom, 而 Cargo 使用另一组功能针对 nom 构建 cexpr 和 nmea。

我想要一种方法来防止我维护的 nmea 板条箱的这种错误使用。

我想要像 "`nom` compiled with wrong features" 这样的编译时错误,或者强制 Cargo 构建 nom 的两个变体。

我在 nmea/Cargo.toml 中尝试过这样的事情:

nom = { version = "3.1.0", default-features = false }

这没有改变; cexpr 和 nmea 组合时仍然存在编译时错误。

已知问题,相关链接:

cargo issue 1

cargo issue 2

cargo rfc

简短摘要:

crate's features are supposed to be additive

换句话说,crate 中的每个特性应该只附加功能, 不改变 API。不幸的是,没有好的文档描述这个问题, 并且至少在这一刻没有自动化测试这个不变量。 此特定问题与 nom 错误 (github issue) 有关, 引用自那里:

The problem here is that, when using "simple errors", the type nom::simple_errors::Err<E> is simply a type alias of nom::ErrorKind<E>, while with "verbose errors" the type nom::verbose_errors::Err<E> is a dedicated enum, so the "with-feature" and "without-feature" interfaces are incompatible.