【发布时间】:2021-08-29 13:32:30
【问题描述】:
我的问题似乎与Rust error "cannot infer an appropriate lifetime for borrow expression" when attempting to mutate state inside a closure returning an Iterator 密切相关,但我认为不一样。所以,这个
use std::iter;
fn example(text: String) -> impl Iterator<Item = Option<String>> {
let mut i = 0;
let mut chunk = None;
iter::from_fn(move || {
if i <= text.len() {
let p_chunk = chunk;
chunk = Some(&text[..i]);
i += 1;
Some(p_chunk.map(|s| String::from(s)))
} else {
None
}
})
}
fn main() {}
不编译。编译器说它无法确定&text[..i] 的适当生命周期。这是我能想到的最小的例子。这个想法是,有一个内部状态,它是text 的一部分,迭代器返回从该内部状态分配的新字符串。我是 Rust 的新手,所以也许这一切都很明显,但是我将如何注释生命周期以便编译?
请注意,此示例与链接示例不同,因为 point 被作为引用传递,而 text 被移动。另外,答案到现在已经一年半了,所以也许有更简单的方法。
编辑: 添加了p_chunk 以强调chunk 需要在对next 的调用中保持不变,因此不能是闭包的本地,但应该被它捕获。
【问题讨论】:
-
这是一个尝试创建self-referential struct 的示例。
text被移入闭包中,chunk也被移入闭包中,指的是text的内容。结果是一个自引用结构,当前借用检查器不支持。 (虽然自引用结构通常是不安全的,但在 这种情况 中它是安全的,因为text是堆分配的,没有变异,并且不会逃脱闭包,所以足够聪明的借用checker 可以证明你正在尝试做的事情是安全的。) -
目前尚不清楚这是否会导致错误,尽管很有可能。您引用的讨论的答案说,可以通过选项引用,但之后不能移动结构。在我的例子中,自引用是在
text和chunk被移动到位之后创建的,并且它们永远不会再次移动,所以原则上它应该可以工作。但如果它确实是借用检查器的边缘案例,我可能应该提交一个错误。 -
它原则上应该可以工作,但众所周知,当前的借用检查器不支持它。 (支持将需要多个新功能:借用检查器应该处理特殊情况的堆分配类型,例如
Box或String,其移动不会影响对其 contnet 的引用,在这种情况下 和也证明你没有调整大小或mem::replace()关闭了String。)当然你仍然可以提交错误报告,但你可以确定所有上述限制肯定已经为开发人员所熟悉。跨度> -
感谢您的澄清。也许发布您的评论作为答案,以便我可以关闭问题?
-
我最初没有回答,因为已经有很多关于自引用结构的问题和答案,但是现在关于 this 案例的内容足够多,它可能值得回答,所以我现在发布了一个。
标签: rust