以下
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>
是否提供了必要的类型信息?
答案 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)