Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

rust - When returning the outcome of consuming a StdinLock, why was the borrow to stdin retained?

Given the following function:

use std::io::{BufRead, stdin};

fn foo() -> usize {
    let stdin = stdin();
    let stdinlock = stdin.lock();
    stdinlock
        .lines()
        .count()
}

This fails to compile with the following error:

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

I find this surprising because the outcome of consuming the lock (via lines) does not retain any references to the original source. In fact, assigning the same outcome to a binding before returning works just fine (Playground).

fn bar() -> usize {
    let stdin = stdin();
    let stdinlock = stdin.lock();
    let r = stdinlock
        .lines()
        .count();
    r
}

This suggests that returning a "consumed lock" immediately has led to the lock attempting to live longer than the locked content, much in an unusual way. All references that I looked into usually point out that the order of declaration matters, but not how the returned objects can affect the order in which they are released.

So why is the former function rejected by the compiler? Why is the lock being seemingly retained for longer than expected?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This seems to be a bug in the compiler. You can make the compiler happy by using an explicit return statement:

use std::io::{stdin, BufRead};

fn foo() -> usize {
    let stdin = stdin();
    let stdinlock = stdin.lock();
    return stdinlock
        .lines()
        .count();
}

fn main() {}

playground

As mentioned in the comments, there are multiple Rust issues related to this:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...