我一直在使用Rust搞乱特性,我遇到了一个问题。这是一些代码:
struct Foo;
trait Bar {}
impl Bar for Foo {}
fn bar<B: Bar>(bar: B) {}
fn barr<B: Bar>() {
bar(Foo); // 1. THIS WILL WORK
let foo: B = Foo; // 2. THIS WILL NOT WORK
let foo_vec: Vec<B> = vec![Foo]; // 3. THIS WILL NOT WORK
}
这会产生错误:
error[E0308]: mismatched types
--> src/main.rs:11:18
|
11 | let foo: B = Foo; // 2. THIS WILL NOT WORK
| ^^^ expected type parameter, found struct `Foo`
|
= note: expected type `B`
found type `Foo`
error[E0308]: mismatched types
--> src/main.rs:12:32
|
12 | let foo_vec: Vec<B> = vec![Foo]; // 3. THIS WILL NOT WORK
| ^^^ expected type parameter, found struct `Foo`
|
= note: expected type `_`
found type `Foo`
为什么不#2&amp; #3工作?我怎样才能让编译器知道Foo
确实有Bar
impl
?
另一个考试:
struct Foo<B: Bar> {
bar: Option<B>,
}
struct Foo2;
trait Bar {}
impl<B: Bar> Bar for Foo<B> {}
impl Bar for Foo2 {}
fn bar<B: Bar>(bar: B) {}
fn circle_vec<B: Bar>() {
bar(Foo2); // 1. WORKS
Foo { bar: Some(Foo { bar: None }) }; // 2. WILL NOT WORK
}
这会给我这个错误:
error[E0282]: type annotations needed
--> src/main.rs:17:21
|
17 | Foo { bar: Some(Foo { bar: None }) }; // 2. WILL NOT WORK
| ^^^ cannot infer type for `B`
答案 0 :(得分:7)
你有两个不同的问题所以我想我会写两个不同的答案。
在您的第一个代码示例中,2和3不起作用,因为B是输入类型参数; barr
的调用者决定B是什么。但是,您试图将其强制为Foo
。
我们假设我们有Bar
的另一个实现:
struct Quux;
impl Bar for Quux {}
我们假设我们这样称呼barr
:
barr::<Quux>()
barr
基本上会编译为:
fn barr() {
bar(Foo);
let foo: Quux = Foo;
let foo_vec: Vec<Quux> = vec![Foo];
}
Foo
和Quux
不兼容,Vec<Foo>
和Vec<Quux>
也不兼容。
如果您尝试创建任意Bar
个对象的向量,则需要以非泛型方式使用Bar
。由于特征类型未标注,您无法将它们直接存储在Vec
中,因此您必须使用Vec<Box<Bar>>
,Vec<&Bar>
或其他包装指针的类型。
fn barr() {
bar(Foo);
let foo: Box<Bar> = Box::new(Foo);
let foo_vec: Vec<Box<Bar>> = vec![Box::new(Foo) as Box<Bar>];
}
在第二个代码示例中,错误是None
具有类型Option<T>
,并且编译器无法推断T
的适当类型。我们可以像这样明确指定T
:
fn circle_vec<B: Bar>() {
bar(Foo2);
Foo {
bar: Some(Foo { bar: None::<Foo2> }),
};
}