返回消费 StdinLock 的结果时,为啥要保留对 stdin 的借用?
Posted
技术标签:
【中文标题】返回消费 StdinLock 的结果时,为啥要保留对 stdin 的借用?【英文标题】:When returning the outcome of consuming a StdinLock, why was the borrow to stdin retained?返回消费 StdinLock 的结果时,为什么要保留对 stdin 的借用? 【发布时间】:2017-09-21 06:10:34 【问题描述】:给定以下函数:
use std::io::BufRead, stdin;
fn foo() -> usize
let stdin = stdin();
let stdinlock = stdin.lock();
stdinlock
.lines()
.count()
编译失败,出现以下错误:
error: `stdin` does not live long enough
--> src/main.rs:12:1
|
7 | let stdinlock = stdin.lock();
| ----- borrow occurs here
...
11 |
| ^ `stdin` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
我觉得这很令人惊讶,因为使用锁的结果(通过lines
)没有保留对原始源的任何引用。事实上,在返回之前为绑定分配相同的结果就可以了 (Playground)。
fn bar() -> usize
let stdin = stdin();
let stdinlock = stdin.lock();
let r = stdinlock
.lines()
.count();
r
这表明立即返回“已使用的锁”会导致锁尝试比被锁定的内容更长的时间,这很不寻常。我研究的所有引用通常都指出声明的顺序很重要,但返回的对象如何影响它们被释放的顺序并不重要。
那么为什么前一个函数会被编译器拒绝呢?为什么锁的保留时间似乎比预期的要长?
【问题讨论】:
哦。有趣! 有人提出错误报告吗? @Veedrac:我不是不知道,我一直在寻找解释,因为经验一次又一次地证明借用检查器比我的直觉更可靠。再说一次,在这种情况下,看起来越来越有可能发生了什么可疑的事情...... 围绕这个主题有一些未解决的问题。主要的是github.com/rust-lang/rust/issues/37407 关于这个问题的讨论已经在#21114进行。 【参考方案1】:我无法回答您问题的为什么,但我可以声明当前的1 实现非词法生命周期允许编译原始代码:
#![feature(nll)]
use std::io::BufRead, stdin;
fn foo() -> usize
let stdin = stdin();
let stdinlock = stdin.lock();
stdinlock
.lines()
.count()
Playground
1 1.25.0-nightly (2018-01-11 73ac5d6)
【讨论】:
【参考方案2】:这似乎是编译器中的一个错误。您可以使用显式的return
语句让编译器满意:
use std::io::stdin, BufRead;
fn foo() -> usize
let stdin = stdin();
let stdinlock = stdin.lock();
return stdinlock
.lines()
.count();
fn main()
playground
如 cmets 中所述,有多个与此相关的 Rust 问题:
37407 21114【讨论】:
以上是关于返回消费 StdinLock 的结果时,为啥要保留对 stdin 的借用?的主要内容,如果未能解决你的问题,请参考以下文章
返回executeFetchRequest的NSArray:结果时我应该保留,自动释放还是啥都不做?
为啥我需要保留NSDateFormatter dateFromString的结果:
php中3个小数的计算,如134.7-52.5 - 82.2,为啥结果不是0而是一个奇怪的科学计数法?