"期望的类型参数,找到结构"

goo*_*goo 8 rust

我一直在使用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
}
Run Code Online (Sandbox Code Playgroud)

这会产生错误:

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`
Run Code Online (Sandbox Code Playgroud)

为什么#2和#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
}
Run Code Online (Sandbox Code Playgroud)

这会给我这个错误:

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`
Run Code Online (Sandbox Code Playgroud)

Fra*_*gné 8

你有两个不同的问题所以我想我会写两个不同的答案.


在您的第一个代码示例中,2和3不起作用,因为B是输入类型参数; barr决定B是什么的是来电者.但是,你试图强迫它Foo.

我们假设我们有另一个实现Bar:

struct Quux;

impl Bar for Quux {}
Run Code Online (Sandbox Code Playgroud)

让我们假设我们这样称呼barr:

barr::<Quux>()
Run Code Online (Sandbox Code Playgroud)

barr 基本上会编译为:

fn barr() {
    bar(Foo);
    let foo: Quux = Foo;
    let foo_vec: Vec<Quux> = vec![Foo];
}
Run Code Online (Sandbox Code Playgroud)

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>];
}
Run Code Online (Sandbox Code Playgroud)

在第二个代码示例中,错误是None具有类型的错误Option<T>,并且编译器无法推断出适当的类型T.我们可以这样明确指定T:

fn circle_vec<B: Bar>() {
    bar(Foo2);
    Foo {
        bar: Some(Foo { bar: None::<Foo2> }),
    };
}
Run Code Online (Sandbox Code Playgroud)

  • 通过使用类型参数,向量的所有元素必须是由调用者指定的相同类型,这意味着您不能在向量中存储Foo,因为`B`可能不是`Foo`.要向向量添加元素,需要类型为"B"的值,您通常将其作为函数的参数接收(`fn barr <B:Bar>(x:B)`). (2认同)