在带有泛型参数的函数中使用具体类型时如何处理“预期类型参数,找到结构”错误?

问题描述 投票:0回答:1

我一直在使用 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 和#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`
generics rust traits
1个回答
14
投票

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


在您的第一个代码示例中,2 和 3 不起作用,因为 B 是一个 input 类型参数;

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> }),
    };
}
© www.soinside.com 2019 - 2024. All rights reserved.