关联类型的界限但是错误:在此上下文中必须知道此值的类型'

时间:2015-04-11 20:30:23

标签: rust

以下

use std::borrow::Borrow;

trait DictLike<'a> {
    type Label: Eq + 'a;
    type ItemsIterator: Iterator<Item=(&'a Self::Label, &'a DictLike<'a>)> + 'a;

    fn items(&self) -> Self::ItemsIterator;

    fn get<Q: ?Sized + Eq>(&self, key: &Q) -> Option<&'a DictLike<'a>>
        where Self::Label: Borrow<Q> {
        for (k,v) in self.items() {
            if k.borrow().eq(key) {
                return Some(v);
            }
        }
        None
    }
}

出错

lib.rs:12:16: 12:26 error: the type of this value must be known in this context
lib.rs:12             if k.borrow().eq(key) {
                         ^~~~~~~~~~

为什么呢?没有ItemsIterator的类型绑定,绑定的Self::Label: Borrow<Q>是否提供了必要的类型信息?

1 个答案:

答案 0 :(得分:3)

这似乎是一个错误:特征声明中的<'a>似乎导致编译器混淆,例如:

trait DictLike<'a> {
    type ItemsIterator: Iterator<Item=u8>;

    fn items(&self) -> Self::ItemsIterator;

    fn get(&self)  {
        for k in self.items() {}
    }
}
<anon>:7:13: 7:14 error: unable to infer enough type information about `_`; type annotations required [E0282]
<anon>:7         for k in self.items() {}
                     ^

删除'a允许编译代码。我已就此提出#24338

幸运的是,有一个解决方法:这似乎只发生在代码在默认方法中,并且将实际实现移动到外部函数时可以正常工作:

use std::borrow::Borrow;

trait DictLike<'a> {
    type Label: Eq + 'a;
    type ItemsIterator: Iterator<Item=(&'a Self::Label, &'a DictLike<'a>)> + 'a;

    fn items(&self) -> Self::ItemsIterator;

    fn get<Q: ?Sized + Eq>(&self, key: &Q) -> Option<&'a DictLike<'a>>
            where Self::Label: Borrow<Q> {
        get(self, key)
    }
}

fn get<'a, X: ?Sized + DictLike<'a>, Q: ?Sized + Eq>(x: &X, key: &Q) -> Option<&'a DictLike<'a>>
        where X::Label: Borrow<Q> {
    for (k,v) in x.items() {
        if k.borrow() == key {
            return Some(v);
        }
    }
    None
}

这在功能上与原始代码没有什么不同,除了它编译的事实。 (我冒昧地将.eq调用切换到==运算符,这对于方法调用来说是更好的糖。)

另外,如果您感觉更喜欢使用迭代器,可以将get写为

x.items()
 .find(|&(k,_)| k.borrow() == key)
 .map(|(_, v)| v)

使用Iterator::findOption::map