我遇到了一个奇怪的类型推断问题,让我有点挠头。
我正在为多种类型的结构实现一个通用特征。我从&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()
的类型。我试图找到一种简洁的方法让编译器知道类型。
答案 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));