[英]“Expected associated type, found `u32`” when using the lifetime of a parameter as trait parameter in where bound
I tried to compile this code ( Playground ): 我试着编译这段代码( 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
}
}
But sadly, it results in this error: 但遗憾的是,它导致了这个错误:
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`
I really don't understand why. 我真的不明白为什么。 Obviously, in this code snippet,
<U32Family as Family<'s>>::Out
is exactly u32
. 显然,在这段代码片段中,
<U32Family as Family<'s>>::Out
正好是u32
。 But Rust seems to think that it's not always the same. 但Rust似乎认为它并不总是一样的。 Why?
为什么? And how can I make it compile?
我怎样才能编译?
Some notes: 一些说明:
type Out: for<'a> Family<'a>;
type Out: for<'a> Family<'a>;
. Family
, everything works. Family
的lifetime参数,一切正常。 Family<'s>
with Family<'static>
in the function signature, everything works. Family<'static>
替换Family<'s>
,一切正常。 EDIT : I can work around this problem by adding: 编辑 :我可以通过添加以下方法解决此问题:
impl U32Family {
fn from<'a>(v: u32) -> <Self as Family<'a>>::Out {
v
}
}
Then I can just say Self::Item::from(0u32)
in the body of next()
. 然后我可以在
next()
的主体中说Self::Item::from(0u32)
next()
。 ( Playground ) ( 游乐场 )
I think it's clear why the error in next()
is gone: U32Family::from
always takes u32
as argument. 我认为这是很清楚,为什么在错误
next()
消失: U32Family::from
始终把u32
作为参数。 Hardcoded. 硬编码。 Never changing.
永不改变。 The bigger question about this workaround is: why does the
from()
method compile fine? 关于这个解决方法的更大问题是:为什么
from()
方法编译良好? So in from()
the compiler somehow knows that <Self as Family<'a>>::Out
is always u32
, but if I try the same in next()
, somehow the compiler doesn't understand that <Self::Item as Family<'s>>::Out
is u32
. 所以在
from()
,编译器以某种方式知道<Self as Family<'a>>::Out
总是u32
,但如果我在next()
尝试相同,那么编译器不知道<Self::Item as Family<'s>>::Out
是u32
。 Now I'm even more confused. 现在我更加困惑。
EDIT2 : first, I suspected that specialization is the problem. 编辑2 :首先,我怀疑专业化是问题所在。 For example, you might write:
例如,您可以写:
impl Family<'static> for U32Family {
type Out = char;
}
Then of course, the compiler would be right in assuming that u32
is not always the same as <Self::Item as Family<'s>>::Out
for any 's
. 然后,当然,编译器会是正确的假设
u32
并不总是一样的<Self::Item as Family<'s>>::Out
任何's
。 However , I think this is not the problem. 但是 ,我认为这不是问题。
First of all, impls that can be specialized need to be marked with the default
keyword . 首先, 需要使用
default
关键字标记可以专用的impl。 I did not do that, so I should be able to assume the associated type is in fact u32
( the RFC talks about something very similar ). 我没有这样做,所以我应该能够假设相关的类型实际上是
u32
( RFC谈论的东西非常相似 )。 But additionally, specialization based on lifetimes is not allowed . 但另外, 不允许基于生命期的专业化。
So by now I tend to think this is a compiler error. 所以到现在为止我倾向于认为这是一个编译器错误。 But I'd love to get another answer!
但是我想得到另一个答案!
I think the problem is that it is a "coincidence" that <Self::Item as Family<'s>>::Out
is u32
for all 's
. 我认为问题是,它是一个“巧合”的是
<Self::Item as Family<'s>>::Out
是u32
所有's
。 The compiler can prove it for any 's
you want, but it can't even express the concept that it is true for all 's
. 编译器可以证明这一点对于任何
's
你想要的,但它甚至不能表达这是所有真正的概念's
。
The work-around you have found is the right approach: add a method to U32Family
which converts a u32
into a <Self as Family<'a>>::Out
. 你已经找到了,周围的工作是正确的做法:添加到方法
U32Family
其中一个转换u32
成<Self as Family<'a>>::Out
。 The body of the method is entirely inside the scope of 'a
, so the compiler can prove that the conversion is type-correct for that 'a
, and therefore that the method is type-correct. 该方法的主体完全在
'a
的范围内,因此编译器可以证明转换对于'a
类型是正确'a
,因此该方法是类型正确的。 Then, at the call-site, you're telling the compiler to use its knowledge about the method. 然后,在调用站点,您告诉编译器使用其有关该方法的知识。
struct U32Family;
...
impl Iterator for Foo {
type Item = U32Family;
So next() must return Option<U32Family>
, whose only possible values are None
and Some(U32Family{})
所以next()必须返回
Option<U32Family>
,其唯一可能的值是None
和Some(U32Family{})
You probably want Item = <U32Family as Family<'static>::Out
which fixes this issue but creates some lifetime issues. 你可能想要
Item = <U32Family as Family<'static>::Out
来修复这个问题,但会产生一些生命周期问题。 (The Item needs a lifetime because Family has one, but you only accept a lifetime on next()
) (该项目需要一生,因为家庭有一个,但你只接受
next()
的生命周期)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.