什么是通过多个通用特征实现通知编译器特定类型的简洁方法?

时间:2018-01-15 12:25:19

标签: generics types casting rust traits

我遇到了一个奇怪的类型推断问题,让我有点挠头。

我正在为多种类型的结构实现一个通用特征。我从&str开始:

struct Bar<'a> {
    baz: &'a str,
}

trait Foo<T> {
    fn foo(&self) -> T;
}

impl<'a> Foo<&'a str> for Bar<'a> {
    fn foo(&self) -> &'a str {
        self.baz
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_str_a() {
        let bar = Bar { baz: "asd" };
        assert_eq!("asd", bar.foo());
    }
}

这很有效 - 当我为u8类型添加另一个实现时会出现问题:

struct Bar<'a> {
    baz: &'a str,
}

trait Foo<T> {
    fn foo(&self) -> T;
}

impl<'a> Foo<&'a str> for Bar<'a> {
    fn foo(&self) -> &'a str {
        self.baz
    }
}

impl<'a> Foo<u8> for Bar<'a> {
    fn foo(&self) -> u8 {
        8
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_str_a() {
        let bar = Bar { baz: "asd" };
        assert_eq!("asd", bar.foo());
    }

    #[test]
    fn test_u8() {
        let bar = Bar { baz: "asd" };
        assert_eq!(8 as u8, bar.foo());
    }
}

在这种情况下,我收到以下错误:

error[E0283]: type annotations required: cannot resolve `Bar<'_>: Foo<_>`
  --> src/main.rs:28:31
   |
28 |         assert_eq!("asd", bar.foo());
   |                               ^^^

如果我将值存储在变量中,它可以工作:

let foo: &str = bar.foo();

在我的生产代码中,我做了很多断言,这会让事情变得有些混乱。我也试过了bar.foo() as &str但是也失败了,因为编译器也不知道bar.foo()的类型。我试图找到一种简洁的方法让编译器知道类型。

1 个答案:

答案 0 :(得分:2)

使用 turbofish ::<>)将type参数传递给trait:

assert_eq!("asd", Foo::<&str>::foo(&bar));

您还可以使用fully-qualified syntax来消除方法所属的特征:

// This is "type-qualified" and equivalent to `Foo::<&str>::foo(&bar)`
assert_eq!("asd", <_ as Foo<&str>>::foo(&bar));

// This is "fully qualified"
assert_eq!("asd", <Bar as Foo<&str>>::foo(&bar));