在 Rust 中调用泛型类型的方法

bet*_*ken 2 rust

我是 Rust 的新手,对泛型类型的使用有点困惑。

考虑以下场景:

我可以像这样创建一个 Date 类型:

use chrono::prelude::*;

fn main() {
  let date = Utc.ymd(2021, 1, 1);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我创建一个函数foo来做类似的事情:

use chrono::prelude::*;

fn foo<Tz: TimeZone>(date: Date<Tz>) {
  let other_date = Tz.ymd(2020, 1, 1);
}


fn main() {
  let date = Utc.ymd(2021, 1, 1);

  foo(date);
}

Run Code Online (Sandbox Code Playgroud)

我希望Tz被替换为Utc,并Tz.ymd等效于Utc.ymd,但事实并非如此:

error[E0423]: expected value, found type parameter `Tz`
 --> src/main.rs:4:20
  |
4 |   let other_date = Tz.ymd(2020, 1, 1);
  |                    ^^ not a value
Run Code Online (Sandbox Code Playgroud)

这让我认为它需要先实例化?但是为什么一开始就不需要呢?我在这里误解了什么?

tre*_*tcl 5

chrono::offset::Utc是一个类似单元的 struct。这意味着它既是具有单个值的类型的名称,又是值本身的名称,例如()既是类型又是值。这是一个方便的功能,但有时会令人困惑。

Utc.ymd(2021, 1, 1)您使用Utc作为值。只有值可以使用.syntax.¹然而,在fooTz是一个类型参数。它可以是实现 的任何类型TimeZone,因此您不能凭空创建type的Tz。不过,你可以做的是采取timezoneDate<Tz>这是在通过了:

fn foo<Tz: TimeZone>(date: Date<Tz>) {
    let other_date = date.timezone().ymd(2020, 1, 1);
}
Run Code Online (Sandbox Code Playgroud)

这会克隆Tz属于 的date并使用克隆创建other_date.


¹ 的完全限定版本Utc.ymd(2021, 1, 1)<Utc as TimeZone>::ymd(&Utc, 2021, 1, 1)第一个Utc类型 Utc,第二个是 Utc