这是什么意思? "This is precisely because a library should not be deterministically recompiled for all users of the library."

what does this mean? "This is precisely because a library should not be deterministically recompiled for all users of the library."

我是 Rust 的新手,正在尝试了解 Cargo 的东西。我在他们的常见问题解答中阅读了有关 "why do binaries have Cargo.lock in version control, but not libraries?" 的内容,但不明白这是什么意思。

”依赖于该库的用户不会检查该库的Cargo.lock(即使它存在)。这恰恰是因为一个库不应该为该库的所有用户确定性地重新编译。

如果一个库最终被多个依赖项传递使用,很可能只需要该库的一个副本(基于 semver 兼容性)。如果 Cargo 使用了所有依赖项的 Cargo.lock 文件,那么可以使用库的多个副本,甚至可能会发生版本冲突。"

如果有人能解释一下,我将不胜感激。谢谢

假设我们有以下板条箱:

  • string-tools:这是一种常用的库,导出一个 FastString 结构,可以更快地实现一些常用功能。这个库有两个版本:1.0.1 和 1.0.2。最近发布了 1.0.2 版本。
  • database:一个与您最喜欢的数据库接口的库。它需要做一些字符串处理,所以它使用 string-tools 库。 database 中的一种 public 方法具有如下签名:
    fn get_username(id: u64) -> string_tools::FastString
    
    该库没有机会或需要更新到 string-tools 的 1.0.2 版 - 也许它不受补丁中修复的任何错误的影响。因此,Cargo.lock 将 string-tools 的版本固定为 1.0.1.
  • client:该库用于与客户端交互。它还依赖于 string-tools,并且有一个像这样的方法:
    fn show_name(name: string_tools::FastString)
    
    该库使用的是最新版本 string-tools,版本 1.0.2。这也是其 Cargo.lock.
  • 中的版本

您想编写一个使用 databaseclient 库的网站。当您构建项目时,Cargo 会使用 Cargo.lock 中指定的版本编译每个库的依赖项。这意味着 database 使用 string-tools 的 1.0.1 版,而 client 使用 1.0.2 版。但现在假设您编写了如下代码:

client::show_name(database::get_username(id));

这个应该编译。毕竟get_username函数returns一个string_tools::FastString,被show_name函数接受。但事实并非如此!那是因为 get_username 返回的 FastString 来自 string_tools 的 1.0.1 版本,而 show_name 想要来自 1.0.2 版本的 FastString!这行不通;毕竟,在为 1.0.2 版本编写 string-tools 的补丁时,作者可能会向该类型添加一个额外的字段。编译器没有任何合理的做法。

让 Cargo 忽略库上的 Cargo.lock 文件可以避免此类问题。相反,它所做的是针对 string_tools 的 1.0.2 版本编译 databaseclient。这是正确的,因为 1.0.1 和 1.0.2 是“semver 兼容版本”。这意味着可以将一个换成另一个,事情仍然必须编译。现在您不再遇到编译器错误,因为一个函数 returns 和另一个函数接受的类型不再不同。