我试着编译这段代码(Playground):
trait Family<'a> {
type Out;
}
struct U32Family;
impl<'a> Family<'a> for U32Family {
type Out = u32;
}
trait Iterator {
type Item;
fn next<'s>(&'s mut self) -> <Self::Item as Family<'s>>::Out
where
Self::Item: Family<'s>;
}
struct Foo;
impl Iterator for Foo {
type Item = U32Family;
fn next<'s>(&'s mut self) -> <Self::Item as Family<'s>>::Out
where
Self::Item: Family<'s>,
{
0u32 // <-- in real code, this is somehow calculated
}
}
Run Code Online (Sandbox Code Playgroud)
但遗憾的是,它导致了这个错误:
error[E0308]: mismatched types
--> src/main.rs:28:9
|
24 | fn next<'s>(&'s mut self) -> <Self::Item as Family<'s>>::Out
| ------------------------------- expected `<U32Family as Family<'s>>::Out` because of return type
...
28 | 0u32
| ^^^^ expected associated type, found u32
|
= note: expected type `<U32Family as Family<'s>>::Out`
found type `u32`
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么.显然,在这段代码中,<U32Family as Family<'s>>::Out确实如此u32.但Rust似乎认为它并不总是一样的.为什么?我怎样才能编译?
一些说明:
type Out: for<'a> Family<'a>;.所以这不是适用于我的解决方法.Family,一切正常.Family<'s>用Family<'static>的函数签名,一切正常.编辑:我可以通过添加以下方法解决此问题:
impl U32Family {
fn from<'a>(v: u32) -> <Self as Family<'a>>::Out {
v
}
}
Run Code Online (Sandbox Code Playgroud)
然后我可以Self::Item::from(0u32)在身体中说出来next().(游乐场)
我认为很明显为什么错误next()消失了:U32Family::from总是把它u32作为参数.硬编码.永不改变.关于这种解决方法的更大问题是:为什么from()方法编译正常?所以from()编译器在某种程度上知道<Self as Family<'a>>::Out永远u32,但如果我尝试相同的next(),莫名其妙的编译器不明白<Self::Item as Family<'s>>::Out的u32.现在我更加困惑.
编辑2:首先,我怀疑专业化是问题所在.例如,您可以写:
impl Family<'static> for U32Family {
type Out = char;
}
Run Code Online (Sandbox Code Playgroud)
当然,编译器会认为u32它并不总是与<Self::Item as Family<'s>>::Out任何一个相同's.但是,我认为这不是问题.
首先,需要使用default关键字标记可以专门化的impl .我没有这样做,所以我应该能够假设相关的类型实际上u32(RFC谈论的东西非常相似).但另外,不允许基于生命期的专业化.
所以到现在为止我倾向于认为这是一个编译器错误.但是我想得到另一个答案!
struct U32Family;
...
impl Iterator for Foo {
type Item = U32Family;
Run Code Online (Sandbox Code Playgroud)
因此 next() 必须返回Option<U32Family>,其唯一可能的值是None和Some(U32Family{})
您可能希望Item = <U32Family as Family<'static>::Out它可以解决此问题,但会产生一些终生问题。(该物品需要终生,因为家庭有一个,但您只接受终生next())