Bounds on associated types but 'error: the type of this value must be known in this context'

Bounds on associated types but 'error: the type of this value must be known in this context'

以下

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> 不提供必要的类型信息吗?

这似乎是一个错误:特征声明中的 <'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::find and Option::map.