输入所需的注释 - 为什么关联类型的处理方式不同?

时间:2016-04-16 21:38:22

标签: rust

在以下程序(play)中,FooBar特征提供bar方法,但bar返回的对象的实际类型似乎是隐藏的。如果我使用类型参数而不是关联类型,它可以工作(play)。

为什么关联类型的处理方式不同?或者我做错了吗?

use std::ops::DerefMut;

pub trait FooBar: Sized {
    type Assoc: Sized + DerefMut<Target=Self>;

    fn foo(&mut self) -> Option<Self::Assoc>;

    fn bar(mut this: Self::Assoc) -> Result<Self::Assoc, Self::Assoc> {
        unimplemented!()
    }
}

#[derive(Debug)]
struct Test(u32);

impl FooBar for Test {
    type Assoc = Box<Test>;
    fn foo(&mut self) -> Option<Self::Assoc> {
        unimplemented!()
    }
}

fn main() {
    let mut tt = Test(20);
    let tt_foo: Box<Test> = tt.foo().unwrap(); // this is ok
    let tt_bar: Box<Test> = FooBar::bar(Box::new(tt)).unwrap(); // but not this
    assert_eq!(tt_bar.0, 20);
}

2 个答案:

答案 0 :(得分:4)

如果你的方法是

fn bar(mut this: Self::Assoc) -> Result<Self::Assoc, Self::Assoc>

你尝试用

调用它
FooBar::bar(Box::new(tt))

Rust怎么知道Self是什么类型的? Box::new(tt) Self::Assoc是正确的,但您无法从中获得Self,有几种类型可能具有相同的Assoc

这就是rustc抱怨的内容:

  

需要输入注释

您必须注释Self的类型:

let tt_bar: Box<Test> = <Test as FooBar>::bar(Box::new(tt)).unwrap();

或等效地:

let tt_bar: Box<Test> = Test::bar(Box::new(tt)).unwrap();

答案 1 :(得分:1)

问题是您正在尝试从特征中访问关联的类型。您只能从实现特征的类型访问它,例如从Test

let tt_bar: Box<Test> = Test::bar(Box::new(tt)).unwrap();

FooBar::Assoc不是具体类型,因此您无法使用它。当您为FooBar实施Test时,您为Test::Assoc提供了一个具体类型,可以访问:

type Assoc = Box<Test>;

在具有泛型类型的代码中,使用具体类型创建了FooBar::bar的新副本。因为您请求了Box<Test>,所以新功能的签名将是:

fn bar(mut this: Box<Test>) -> Result<Box<Test>, Box<Test>>

Box<Test>是一种具体的类型,所以它有效。