关联类型的生命周期绑定被拒绝,尽管它似乎是有效的 [英] lifetime bound on associated type is rejected although it seems valid

查看:71
本文介绍了关联类型的生命周期绑定被拒绝,尽管它似乎是有效的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段无法编译的代码,可以将其简化为以下代码段:

I have a piece of code that does not compile and that can be reduced to this snippet:

use std::error::Error;
use std::convert::TryFrom;

// A trait that provides methods for parsing data into a type T.
pub trait Deserializable<T> {
    // some methods
}

pub struct MyBuffer<'a> {
    inner: &'a [u8]
}

impl<'a, T> Deserializable<T> for MyBuffer<'a> 
where
    T: TryFrom<&'a [u8]>,
    <T as TryFrom<&'a [u8]>>::Error: Error + Sync + Send + 'static 
{
    // some methods to implement
}

fn main() {}

编译器拒绝该程序,并显示一个令人困惑的错误消息:

The compiler rejects this program with a confusing error message:

error[E0310]: the associated type `<T as std::convert::TryFrom<&[u8]>>::Error` may not live long enough
  --> src/main.rs:13:13
   |
13 | impl<'a, T> Deserializable<T> for MyBuffer<'a> 
   |             ^^^^^^^^^^^^^^^^^
   |
   = help: consider adding an explicit lifetime bound `<T as std::convert::TryFrom<&[u8]>>::Error: 'static`...
note: ...so that the type `<T as std::convert::TryFrom<&[u8]>>::Error` will meet its required lifetime bounds
  --> src/main.rs:13:13
   |
13 | impl<'a, T> Deserializable<T> for MyBuffer<'a> 
   |             ^^^^^^^^^^^^^^^^^

该错误表明我添加了'static生命周期限制,但是我已经添加了它:

The error suggests that I add the 'static lifetime bound, but I already added it:

consider adding an explicit lifetime bound `<T as std::convert::TryFrom<&[u8]>>::Error: 'static`

有人可以解释为什么该程序无法编译,和/或如何解决(如果可能)吗?在我看来,即使T本身绑定到'a,也可能 'static.

Can someone explain why this program does not compile, and/or how to fix it (if possible)? It seems to me that it should be possible to have <T as TryFrom<&'a [u8]>>::Error to be 'static even though T itself is bound to 'a.

我希望Error成为'static的原因是我使用failure

The reason I want Error to be 'static is that I use failure and failure::Fail is implemented for Send + Sync + Error + 'static.

推荐答案

这似乎是编译器推理寿命和关联类型的能力中的空白.

This appears to be a gap in the compiler's ability to reason about lifetimes and associated types.

有时,为了帮助编译器,您可以添加通用参数来别名关联类型.此参数不会计数",因为它不会使项目变得更通用",但是由于在使用时解析了通用而不是声明,因此它推迟了类型检查的困难部分,直到知道确切的类型为止.换句话说:编译器也许可以证明任何 specific T::Error都可以工作,但是并不能完全证明 every T::Error必须可以工作,所以我们引入一个绑定为T::Error的新参数E,并告诉编译器仅在尝试使用它时才弄清E是什么.

Sometimes, in order to help the compiler, you can add a generic parameter to alias an associated type. This parameter doesn't "count" in that it doesn't make the item "more generic", but because generics are resolved at use instead of declaration, it defers the hard part of type checking until the exact types are known. In other words: the compiler might be able to prove that any particular T::Error works, but it can't quite prove that every T::Error must work, so we introduce a new parameter E which is bound to be T::Error and tell the compiler to figure out what E is only when we try to use it.

以下作品(游乐场):

impl<'a, T, E> Deserializable<T> for MyBuffer<'a>
where
    T: TryFrom<&'a [u8], Error = E>,
    E: Error + Sync + Send + 'static,
{
    // ...
}

代替边界T::Error,我们引入一个具有所需边界的新类型参数E,并约束T,以使其TryFrom::ErrorE.从逻辑上讲(据我所知)与您编写的内容相同,但是编译时没有任何抱怨.

Instead of bounding T::Error, we introduce a new type parameter E with the bounds we want and constrain T such that its TryFrom::Error is E. This is logically (as far as I can tell) the same thing as what you wrote, but it compiles without complaint.

我找不到与此相关的官方文档;它可能是求解器的固有限制,或者仅仅是一个错误.

I can't find official documentation that refers to this; it may be an inherent limitation of the solver, or merely a bug.

这篇关于关联类型的生命周期绑定被拒绝,尽管它似乎是有效的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆