我如何让impl Trait使用适当的生命周期来对其中有另一个生命周期的值进行可变引用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我如何让impl Trait使用适当的生命周期来对其中有另一个生命周期的值进行可变引用?相关的知识,希望对你有一定的参考价值。

我有一个有生命的结构:

struct HasLifetime<'a>( /* ... */ );

有一个特征Foo的实现:

impl<'a, 'b: 'a> Foo for &'a mut HasLifetime<'b> { }

我想实现以下功能:

fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut Lifetime<'b>) -> impl Foo {
    bar
}

这将无法编译,因为返回的impl仅对'a有效。但是,指定impl Foo + 'a会导致:

error[E0909]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
 --> src/main.rs:7:60
  |
7 | fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut HasLifetime<'b>) -> impl Trait + 'a {
  |                                                            ^^^^^^^^^^^^^^^
  |
note: hidden type `&'a mut HasLifetime<'b>` captures the lifetime 'b as defined on the function body at 7:1
 --> src/main.rs:7:1
  |
7 | fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut HasLifetime<'b>) -> impl Trait + 'a {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

具有盒装特征对象的看似等效的函数编译:

fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut Lifetime<'b>) -> Box<Foo + 'a> {
    Box::new(bar)
}

如何用bar_to_foo定义impl Trait

Playground link

答案

您需要指明返回的值是基于多个生命周期构建的。但是,您不能使用impl Trait的多个生命周期边界,并尝试这样做doesn't have a useful error message

a trick you can use涉及创建具有生命周期参数的虚拟特征:

trait Captures<'a> {}
impl<'a, T: ?Sized> Captures<'a> for T {}

fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut HasLifetime<'b>) -> impl Trait + Captures<'b> + 'a {
    bar
}

值得庆幸的是,这个only occurs when the "hidden" lifetime is invariant,因为引用是可变的。

以上是关于我如何让impl Trait使用适当的生命周期来对其中有另一个生命周期的值进行可变引用?的主要内容,如果未能解决你的问题,请参考以下文章

终身省略是不是适用于 trait impls 中的方法?

Rust编程语言入门之泛型Trait生命周期

impl 上的第一个显式生命周期说明符是啥意思?

Rust impl trait

是否可以在特征定义中使用“impl Trait”作为函数的返回类型?

无法为返回引用的闭包推断适当的生命周期