具有借用的构造函数的特征无法推断使用时的提升时间

问题描述

我需要一个特性,它允许我构造一个借用对象的对象。在下面的例子中就是 PaperBin。 https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=78fb3f88b71bc226614912001ceca65b

trait GarbageBin<'a,'b>{
    fn new(rubbish: &'b Paper<'a>) -> Self;
}
struct PaperBin<'a,'b> {
    rubbish: &'b Paper<'a>
}
struct Paper<'a> {
    matter: &'a [u8]
}
impl<'a,'b> GarbageBin<'a,'b> for PaperBin<'a,'b> {
    fn new(rubbish: &'b Paper<'a>) -> Self{
        Self {
            rubbish: rubbish
        }
    }
}
fn create_bin_with_rubbish<'a,'b,T>()
    where T: GarbageBin<'a,'b>
{
    let matter = &[1][..];
    let rubbish = Paper{matter};
    This gives an error:
    //let garbage_bin = T::new(&rubbish);
}

#[test]
fn run() {
    create_bin_with_rubbish::<PaperBin>();
}

我需要创建一般根据函数调用确定的 GarbageBins,如示例中所示。对于 Trait 的 new() 关联函数中的固定类型 Paper,此示例看起来可能是不必要的。这应该成为实际代码中的 Trait 对象。

如何实现泛型类型T的garbage_bin的创建?

这是我收到的错误消息,如果我取消注释该行:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src\reference_to_reference\mod.rs:23:23
   |
23 |     let garbage_bin = T::new(&rubbish);
   |                       ^^^^^^
   |
note: first,the lifetime cannot outlive the lifetime `'a` as defined on the function body at 18:28...
  --> src\reference_to_reference\mod.rs:18:28
   |
18 | fn create_bin_with_rubbish<'a,T>()
   |                            ^^
note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 18:31...
  --> src\reference_to_reference\mod.rs:18:31
   |
18 | fn create_bin_with_rubbish<'a,T>()
   |                               ^^
note: ...so that the types are compatible
  --> src\reference_to_reference\mod.rs:23:23
   |
23 |     let garbage_bin = T::new(&rubbish);
   |                       ^^^^^^
   = note: expected `GarbageBin<'_,'_>`
              found `GarbageBin<'a,'b>`

解决方法

您的直接问题是 T: GarbageBin<'a,'b> 其中 'a'bcreate_bin_with_rubbish 的参数,因此必须比对该函数的调用寿命更长——但实际生命周期传递给 {{ 1}} 仅在函数内部,因此不满足这些界限。

不是使用生命周期 T::newcreate_bin_with_rubbish 参数化 'a,解决此问题的一种方法是使用 HRTB(更高排名的特征边界):

'b

然而,fn create_bin_with_rubbish<T>() where T: for<'a,'b> GarbageBin<'a,'b>, 隐含地要求 PaperBin,目前 HRTB 不支持此类边界。但这本身就表明第二个生命周期参数是不必要的:请记住,生命周期参数仅意味着“生命至少与……一样长”,并且同一参数的多个实例可以代表不同的具体生命周期(只要它们每个满足相同的界限)。所以让我们简化一下:

'a: 'b

最后,使用 HRTB 确实需要断开 struct PaperBin<'a> { rubbish: &'a Paper<'a>,} 的生命周期与其实现者 GarbageBin 之间的直接链接——但这是有道理的,因为您试图传入 {{1} } 类型而不知道其生命周期参数,然后在其上调用 PaperBin 的构造函数方法以获取具有特定生命周期参数的 PaperBin。所以现在我们实现了 GarbageBin——但我们仍然需要构造函数来返回一个 PaperBin 的实例,我们为其添加一个关联类型:

GarbageBin<'a> for PaperBin<'_>

See it on the Playground

使用 GAT(泛型关联类型),它是 currently 一个不稳定的特性,您可以将生命周期参数从特征推送到关联类型,从而不需要 HRTB:

PaperBin<'a>

See it on the Playground