为什么我有时需要"Use"一些我没有真正在 Rust 中使用的东西?



考虑以下代码:

use chrono::{Local, NaiveDate};
fn main() {
let d = Local::now().naive_local().date();
println!("{}", d.num_days_from_ce());
}

编译失败,并出现奇怪的错误,"在当前作用域内,没有为struct NaiveDate找到名为num_days_from_ce的方法"。

什么?没有方法名?就在文档里呢?

我花了一段时间才弄清楚我需要将Datelike添加到我从chrono使用的东西中。我的问题是,为什么?为什么要强迫消费者手动导入我们不直接使用的依赖项呢?这并不是Rust中这些必要的幻影导入的唯一情况……🧐

也许Rust有什么我不理解的地方,或者这个库有什么可以修改的地方,这样消费者就不需要在这种情况下使用DateLike了。

还有,为什么编译器不能推荐要带入当前作用域的内容?

该语法的另一个问题是,它会产生一个编译器警告,警告这些必要的幻影导入未被使用。因此,没有办法让我的代码编译干净…😔

warning: unused imports: `Datelike`, `NaiveDate`, `Weekday`
--> src/bin/foo/bar.rs:25:18
|
25 |     use chrono::{Datelike, Duration, Local, NaiveDate, Weekday};
|                  ^^^^^^^^                   ^^^^^^^^^  ^^^^^^^

Rust有一个规则,你不能使用trait方法,除非trait在作用域中。如果trait不在作用域中,你仍然可以使用这些函数,只是不能使用后缀方法语法。

use chrono::Local;
fn main() {
let d = Local::now().naive_local().date();
println!("{}", chrono::Datelike::num_days_from_ce(&d));
}

但是在几乎所有情况下,您都将把trait引入作用域并使用方法语法。许多标准库特性,如Iterator,是自动导入的。

该规则的存在是由于API的原因。任何人都可以在外部类型上实现trait,所以如果你的两个依赖项都有一个带有同名方法的trait,就会产生歧义。依赖关系没有顺序,因此选择一个而不是另一个将是不明确的。如果这会导致错误,则意味着实现trait的crate可能是破坏性的API更改。相反,rust要求trait在作用域中,从而避免了这些问题。

这也允许在实际类型有同名方法时轻松调用trait方法。例如,如果一个类型有一个名为borrow的方法,并且也实现了Borrow特性,执行value.borrow()将调用该类型的方法,但是当Borrow在作用域中时,它将调用Borrow::borrow

最新更新