我试图编译此代码(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
    }
}

但是可悲的是,它导致了这个错误:

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`

我真的不明白为什么。显然,在此代码段中,<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
        }
    }
    

    然后,我可以在Self::Item::from(0u32)主体中说next()。 (Playground)

    我认为很清楚为什么next()中的错误消失了:U32Family::from始终将u32作为参数。硬编码。永不改变。关于此解决方法的更大问题是:为什么from()方法可以正常编译?因此,在from()中,编译器以某种方式知道<Self as Family<'a>>::Out始终是u32,但是如果我在next()中尝试相同的操作,则以某种方式,编译器将无法理解<Self::Item as Family<'s>>::Outu32。现在我更加困惑了。

    EDIT2 :首先,我怀疑特化是问题所在。例如,您可以编写:
    impl Family<'static> for U32Family {
        type Out = char;
    }
    

    那么,当然,对于任何u32<Self::Item as Family<'s>>::Out并不总是与's相同,那么编译器将是正确的。但是,我认为这不是问题。

    首先,暗示可以是专门的need to be marked with the default keyword。我没有这样做,所以我应该能够假定关联的类型实际上是u32(the RFC talks about something very similar)。但此外,基于生存期is not allowed的特化。

    因此,到目前为止,我倾向于认为这是编译器错误。但我想再得到一个答案!

    最佳答案

    我认为问题在于,对于所有<Self::Item as Family<'s>>::Out来说u32's是“巧合”。编译器可以针对所需的任何's证明这一点,但它甚至无法表达出对所有's都是正确的概念。

    您找到的解决方法是正确的方法:在U32Family中添加一个方法,该方法可将u32转换为<Self as Family<'a>>::Out。该方法的主体完全在'a的范围内,因此编译器可以证明该'a的转换是类型正确的,因此该方法是类型正确的。然后,在调用现场,您要告诉编译器使用其有关该方法的知识。

    关于rust - “Expected associated type, found ` u32 `”,在将参数的生存期用作受约束位置的特征参数时,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51638863/

    10-11 18:33