JAVA 临时变量的生命周期,如何在Rust中延长迭代器适配器内部临时变量的寿命?...

I have a method make_iter() which creates an Iterator with multiple adapters in Rust, which can be simplified as the following MCVE:

fn make_iter(first: &First) -> Box + '_> {

Box::new(first.make_objects().flat_map(|second| {

second

.iter()

.filter(|third| third.as_str() != "t2")

.flat_map(|third| vec![format!("{}.A", third), format!("{}.B", third)].into_iter())

.chain(

vec![

format!("{}.A", second.name()),

format!("{}.B", second.name()),

]

.into_iter(),

)

}))

}

pub fn main() {

let first = First {};

for i in make_iter(&first) {

println!("{}", i);

}

}

struct First {}

impl First {

fn make_objects(&self) -> Box + '_> {

Box::new(

vec![

Second::new("s1".to_string()),

Second::new("s2".to_string()),

Second::new("s3".to_string()),

]

.into_iter(),

)

}

}

struct Second {

name: String,

objects: Vec,

}

impl Second {

fn new(name: String) -> Second {

Second {

name,

objects: vec!["t1".to_string(), "t2".to_string(), "t3".to_string()],

}

}

fn name(&self) -> &str {

&self.name

}

fn iter(&self) -> Box + '_> {

Box::new(self.objects.iter())

}

}

Trying to compile this example yields a lifetime error:

error[E0597]: `second` does not live long enough

--> src/main.rs:3:9

|

3 | second

| ^^^^^^ borrowed value does not live long enough

...

14 | }))

| - `second` dropped here while still borrowed

This is understandable, as the second object is a temporary, and the iterator returned from the same closure attempts to borrow it, failing as second is dropped at the closure's end.

My objective would be to extend the lifetime of this object until the Iterator referencing it is dropped, but I don't know how.

Note that the structure implementations cannot be changed. Rust version is 1.34.2, edition 2018

解决方案

extend the lifetime of this object

You cannot do this, period. It's simply not how things work.

See also:

Here's a simpler reproduction:

use std::iter;

fn example(outer: impl Iterator) {

outer.flat_map(|i| i.iter().map(|v| v.clone()));

}

struct Inner;

impl Inner {

fn iter(&self) -> impl Iterator + '_ {

iter::empty()

}

}

Since you have the restriction of being unable to change Inner, the easiest solution is to be more eager and proactively collect:

fn example(outer: impl Iterator) {

outer.flat_map(|i| i.iter().map(|v| v.clone()).collect::>());

}

The only possibility I know of to avoid that would be to use a crate like rental or owning_ref.

See also:

If you had the possibility of changing Inner, you should make a consuming iterator variant. Then the value does not need to live beyond the closure because the iterator has taken ownership.

use std::iter;

fn example(outer: impl Iterator) {

outer.flat_map(|i| i.into_iter().map(|v| v));

}

struct Inner;

impl Inner {

fn into_iter(self) -> impl Iterator {

iter::empty()

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值