【发布时间】:2022-11-22 19:00:47
【问题描述】:
为了弄清楚为什么我的某些代码无法编译,我创建了以下最小测试。
我正在尝试编写一个函数,它接收类似 &Vec<i32> 的内容并返回可以通过 i32 转换为 Iterator 的内容。
输出不包含任何从输入借来的东西。我的意图是输出比输入具有更长的生命周期。
在我的新手看来,这看起来应该可行。
fn error_1<'a, I: IntoIterator<Item=&'a i32>>(_: I) -> impl IntoIterator<Item=i32> + 'static {
vec![1]
}
但是,当我测试输出是否可以比输入更长寿时......
fn test_e1() {
let v = vec![3];
let a = error_1(&v);
drop(v); // DROP v BEFORE a.. should be ok!?
}
我收到这个错误。
error[E0505]: cannot move out of `v` because it is borrowed
--> src/lib.rs:8:10
|
7 | let a = error_1(&v);
| -- borrow of `v` occurs here
8 | drop(v); // DROP v BEFORE a.. should be ok!?
| ^ move out of `v` occurs here
9 | }
| - borrow might be used here, when `a` is dropped and runs the destructor for type `impl IntoIterator<Item = i32>`
好的 - 所以,rust 担心 IntoIterator 的可能实现可能借了“v”?
Playground Link - broken code
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=41ef3bce0157cc23f824f20eb0651bd9
我试着进一步试验这个......
绝对让我感到困惑的是,为什么下一个测试编译得很好......它似乎有同样的问题,但 rust 很乐意编译它。
fn fine_1<'a, I: IntoIterator<Item=i32>>(_: &I) -> impl IntoIterator<Item=i32> + 'static {
vec![1]
}
fn test_f1() {
let v = vec![3];
let a = fine_1(&v);
drop(v); // DROP v BEFORE a.. should be ok!?
}
Playground link for tweaked, working code
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7e92549aa4e741c4dd0aae289afcf9db
有人可以帮我解释一下第一个代码有什么问题吗?
我如何指定返回类型的生命周期与参数的生命周期完全无关?
只是为了好玩,另一个错误的例子..这次返回与 Vec 无关的东西..同样的错误。
fn error_fn<'a, I: IntoIterator<Item=&'a i32>>(_: I) -> impl Fn() + 'static{
|| {}
}
fn test_fn() {
let v = vec![3];
let a = error_fn(&v);
drop(v);
}
我不想解决这个问题……我可以重构代码。
这里的目标是学习......这暴露了我对生命时间理解的差距......
直到最近,我还以为我已经搞定了:D
值得一提的是,如果我将输入更改为具体类型,而不是 trait impl.. `_: &Vec 一切,再次编译正常。
它似乎是特征相关类型的生命周期,打破了一切......我只是不明白为什么!??
【问题讨论】:
标签: rust traits lifetime-scoping