简体   繁体   English

当使用参数的生命周期作为特征参数时,“预期的关联类型,找到`u32`”

[英]“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: 一些说明:

  • There are a bunch of similar situations where a similar error occurs, but I think this is different from everything I've seen so far. 有很多类似的情况会发生类似的错误,但我认为这与我到目前为止看到的所有内容都不同。
  • I cannot use type Out: for<'a> Family<'a>; 我不能使用type Out: for<'a> Family<'a>; . So that's not a workaround that works for me. 所以这不是适用于我的解决方法。
  • If I remove the lifetime parameter of Family , everything works. 如果我删除Family的lifetime参数,一切正常。
  • If I replace 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>>::Outu32 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 ). 我没有这样做,所以我应该能够假设相关的类型实际上是u32RFC谈论的东西非常相似 )。 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>>::Outu32所有'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> ,其唯一可能的值是NoneSome(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.

相关问题 闭包:预期 u32 找到类型参数 - closures: expected u32 found type parameter 使用相关类型的特征与生命周期参数的生命周期错误 - Lifetime error using associated type of trait with lifetime parameter 预期的约束寿命参数,找到具体的寿命 - Expected bound lifetime parameter, found concrete lifetime 使用带有生命周期参数的特征作为通用界限的问题 - Trouble with using a trait with lifetime parameter as a generic bound 使用泛型关联类型时,如何指示类型参数的生命周期? - How do I indicate a lifetime bound on a type parameter when using generic associated types? Rust 添加与 u32 关联的类型 - Rust adding associated type with u32 预期的约束寿命参数,找到的混凝土寿命[E0271] - Expected bound lifetime parameter, found concrete lifetime [E0271] 如何解决:预期的混凝土寿命,但找到了约束寿命参数 - How to fix: expected concrete lifetime, but found bound lifetime parameter StreamExt.scan() 方法上的“预期绑定生命周期参数,找到具体生命周期” - “expected bound lifetime parameter, found concrete lifetime” on StreamExt .scan() method 使用函数定义特征,该函数返回与一个参数具有相同生命周期的关联类型 - Define a trait with a function that returns an associated type with the same lifetime as one parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM