为什么编译器告诉我考虑使用 `let` 绑定?
Why does the compiler tell me to consider using a `let` binding" when I already am?
我的错误是什么以及如何解决?
fn get_m() -> Vec<i8> {
vec![1, 2, 3]
}
fn main() {
let mut vals = get_m().iter().peekable();
println!("Saw a {:?}", vals.peek());
}
编译器的错误提示 "consider using a let
binding" — 但我已经是:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:6:45
|
6 | let mut vals = get_m().iter().peekable();
| ------- ^ temporary value dropped here while still borrowed
| |
| temporary value created here
7 | println!("Saw a {:?}", vals.peek());
8 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
这显然是一个新手问题——虽然我认为此时我已经写了足够多的 Rust,我已经掌握了借用检查器……显然我还没有。
此题与Using a `let` binding to increase value lifetime类似,但不涉及将表达式分解为多个语句,所以我认为问题不相同。
发生这种情况是因为您正试图 运行 您的 .iter().peekable()
在 get_m()
内部的实际向量上,它被 vals
重新引用。
基本上,您想要这样的东西:
fn get_m() -> Vec<i8> {
vec![1, 2, 3]
}
fn main() {
let vals = get_m();
let mut val = vals.iter().peekable();
println!("Saw a {:?}", val.peek());
}
结果:
Saw a Some(1)
问题是 Peekable
迭代器一直存在到函数的末尾,但它持有对由 get_m
编辑的向量 return 的引用,它只持续那么久作为包含该调用的语句。
这里其实有很多事情要做,我们一步步来吧:
get_m
分配并 return 一个向量,类型为 Vec<i8>
。
- 我们打电话
.iter()
。令人惊讶的是,Vec<i8>
没有 iter
方法,它也没有实现任何具有该方法的特征。所以这里分为三个子步骤:
- 任何方法调用都会检查其
self
值是否实现了 Deref
特性,并在必要时应用它。 Vec<i8>
确实实现了 Deref
,所以我们隐式调用它的 deref
方法。但是,deref
通过引用获取其 self
参数,这意味着 get_m()
现在是出现在左值上下文中的右值。在这种情况下,Rust 会创建一个临时对象来保存该值,并将引用传递给它。 (暂时关注一下!)
- 我们调用
deref
,产生一个 &[i8]
类型的切片借用向量的元素。
- 此切片实现了
SliceExt
特性, 具有 iter
方法。最后!此 iter
还通过引用获取其 self
参数,并且 return 是一个 std::slice::Iter
保存对切片的引用。
- 我们打电话
.peekable()
。和以前一样,std::slice::Iter
没有 peekable
方法,但它确实实现了 Iterator
; IteratorExt
为每个 Iterator
实施;并且 IteratorExt
有 peekable
方法。这将其 self
按值获取,因此 Iter
被消耗,我们在 return 中得到一个 std::iter::Peekable
,再次持有对切片的引用。
- 此
Peekable
然后绑定到变量 vals
,该变量一直存在到函数的末尾。
Peekable
引用其元素的原始 Vec<i8>
的临时保存者现已死亡。哎呀。这是借来的价值不够长寿。
但是临时工死在那里只是因为这是临时工的规则。如果我们给它一个名字,那么只要它的名字在范围内,它就会持续存在:
let vec = get_m();
let mut peekable = vec.iter().peekable();
println!("Saw a {:?}", vals.peek());
我想这就是故事。然而,仍然让我感到困惑的是,为什么即使没有名字,临时工也不会活得更久。 Rust 参考资料说,"A temporary's lifetime equals the largest lifetime of any reference that points to it." 但这里显然不是这种情况。
我的错误是什么以及如何解决?
fn get_m() -> Vec<i8> {
vec![1, 2, 3]
}
fn main() {
let mut vals = get_m().iter().peekable();
println!("Saw a {:?}", vals.peek());
}
编译器的错误提示 "consider using a let
binding" — 但我已经是:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:6:45
|
6 | let mut vals = get_m().iter().peekable();
| ------- ^ temporary value dropped here while still borrowed
| |
| temporary value created here
7 | println!("Saw a {:?}", vals.peek());
8 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
这显然是一个新手问题——虽然我认为此时我已经写了足够多的 Rust,我已经掌握了借用检查器……显然我还没有。
此题与Using a `let` binding to increase value lifetime类似,但不涉及将表达式分解为多个语句,所以我认为问题不相同。
发生这种情况是因为您正试图 运行 您的 .iter().peekable()
在 get_m()
内部的实际向量上,它被 vals
重新引用。
基本上,您想要这样的东西:
fn get_m() -> Vec<i8> {
vec![1, 2, 3]
}
fn main() {
let vals = get_m();
let mut val = vals.iter().peekable();
println!("Saw a {:?}", val.peek());
}
结果:
Saw a Some(1)
问题是 Peekable
迭代器一直存在到函数的末尾,但它持有对由 get_m
编辑的向量 return 的引用,它只持续那么久作为包含该调用的语句。
这里其实有很多事情要做,我们一步步来吧:
get_m
分配并 return 一个向量,类型为Vec<i8>
。- 我们打电话
.iter()
。令人惊讶的是,Vec<i8>
没有iter
方法,它也没有实现任何具有该方法的特征。所以这里分为三个子步骤:- 任何方法调用都会检查其
self
值是否实现了Deref
特性,并在必要时应用它。Vec<i8>
确实实现了Deref
,所以我们隐式调用它的deref
方法。但是,deref
通过引用获取其self
参数,这意味着get_m()
现在是出现在左值上下文中的右值。在这种情况下,Rust 会创建一个临时对象来保存该值,并将引用传递给它。 (暂时关注一下!) - 我们调用
deref
,产生一个&[i8]
类型的切片借用向量的元素。 - 此切片实现了
SliceExt
特性, 具有iter
方法。最后!此iter
还通过引用获取其self
参数,并且 return 是一个std::slice::Iter
保存对切片的引用。
- 任何方法调用都会检查其
- 我们打电话
.peekable()
。和以前一样,std::slice::Iter
没有peekable
方法,但它确实实现了Iterator
;IteratorExt
为每个Iterator
实施;并且IteratorExt
有peekable
方法。这将其self
按值获取,因此Iter
被消耗,我们在 return 中得到一个std::iter::Peekable
,再次持有对切片的引用。 - 此
Peekable
然后绑定到变量vals
,该变量一直存在到函数的末尾。 Peekable
引用其元素的原始Vec<i8>
的临时保存者现已死亡。哎呀。这是借来的价值不够长寿。
但是临时工死在那里只是因为这是临时工的规则。如果我们给它一个名字,那么只要它的名字在范围内,它就会持续存在:
let vec = get_m();
let mut peekable = vec.iter().peekable();
println!("Saw a {:?}", vals.peek());
我想这就是故事。然而,仍然让我感到困惑的是,为什么即使没有名字,临时工也不会活得更久。 Rust 参考资料说,"A temporary's lifetime equals the largest lifetime of any reference that points to it." 但这里显然不是这种情况。