错误:无法推断出有关`_`的足够类型信息;需要输入注释或通用参数绑定

时间:2016-05-23 22:40:14

标签: generics rust

通用标题的道歉。

以下是一些示例代码:

use std::marker::PhantomData;

pub trait Foo {
    fn foo(&self);
}

pub trait Bar<A: Foo> {
    fn bar(&self, a: A);
}

pub struct Test<A, B>
    where A: Foo,
          B: Bar<A>
{
    _phantom_r: PhantomData<A>,
    bars: Vec<B>,
}

impl<A, B> Test<A, B>
    where A: Foo,
          B: Bar<A>
{
    pub fn new() -> Test<A, B> {
        Test {
            _phantom_r: PhantomData,
            bars: Vec::new(),
        }
    }

    pub fn add_bar(&mut self, b: B) {
        self.bars.push(b);
    }
}

fn main() {
    let t = Test::new();
}

Playground

错误是:

<anon>:32:13: 36:22 error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
<anon>:32     let t = Test::new();

我对Rust在推断特质类型方面遇到的问题感到困惑,以及我如何指定它想要的东西。也就是说,我不确定这是否正确,因为我遇到Sized问题:

let t = Test::new() as Test<Foo,Bar<Foo>>;

错误:

<anon>:36:28: 36:46 error: the trait `core::marker::Sized` is not implemented for the type `Foo` [E0277]
<anon>:36     let t = Test::new() as Test<Foo,Bar<Foo>>;

我有两个主要问题:

  1. 为什么Rust无法推断出Test<A,B<A>>
  2. 的特征类型
  3. 使此代码有效的解决方案是什么?

3 个答案:

答案 0 :(得分:6)

简短的回答是你没有告诉它使用什么类型。

解释你的声明:

pub trait Foo {}

“有一个特征Foo

pub trait Bar<A: Foo> {}

“如果你给我一个实施A的{​​{1}}类型,我可以给你一个特征Foo。”

Bar<A>

“如果您提供实施pub struct Test<A, B> where A: Foo, B: Bar<A> {} 的{​​{1}}类型,以及实施A的{​​{1}},我会为您提供Foo类型

B

“让我成为Bar<A>”。这就是问题 - Test<A,B>不是一个类型,它是一个模板,用于创建一个给定两种类型的类型(有一些限制)。在上面的示例中,您没有提供任何此类类型,只是缩小了类似的类型。

要实际使用let t = Test::new(); ,您需要提供以下类型:

Test

Playground

答案 1 :(得分:0)

您可以将第一个错误归结为:

fn main() {
    let v = Vec::new();
}

这里的问题是编译器无法确定向量将包含的具体类型。在您的情况下,您创建了一个结构(Test),可以在不传递AB的具体类型的情况下创建该结构,但基本推理是相同的。

第二个问题是相关的。 FooBar都不是编译时已知大小的具体类型。尝试在需要固定大小的位置(由Sized特征表示)中使用它们将失败。

当您实例化类型时,类型的大小必须,并且通过提供具体类型代替泛型类型参数来完成。

答案 2 :(得分:0)

关于已接受答案的说明 - 已接受的答案涵盖了识别特征的问题,但是该线程中有一些注释可以解释此问题的其他详细信息。为了便于阅读,我在这里总结了其中一个(因为评论有点难以理解)。

Static Dispatch (当您使用上述代码中的特征时使用)将不适用于矢量上的多个具体类型。

例如,举个例子:

trait Foo {
    fn method(&self) -> String;
}
impl Foo for u8 {
    fn method(&self) -> String {
        format!("u8: {}", *self)
    }
}

impl Foo for String {
    fn method(&self) -> String {
        format!("string: {}", *self)
    }
}

struct Test<T: Foo> {
    foos: Vec<T>,
}
impl<T:Foo> Test<T> {
    pub fn do_something(&self, x: T) {
        self.foos.push(x);
    }
}

fn main() {
    let x = 5u8;
    let y = "Hello".to_string();

    let t = Test {foos:Vec::new()};
    t.do_something(x);
    t.do_something(y);
}

这将有效,因为虽然do_something() 可以使用静态调度,但Test::foos 无法。如果我们改为Test改为:

struct Test {
}
impl Test {
    pub fn do_something<T: Foo>(&self, x: T) {
        x.method();
    }
}

它会起作用。 main()函数根本不需要更改(除了删除向量),它完全与Vector导致静态调度(显然)不工作。

在这种情况下,我相信Dynamic Dispatch会起作用 - 但我还不熟悉,只是在这里给出任何深入的答案/例子。希望这有助于未来的读者。