Quando si restituisce il risultato del consumo di uno StdinLock, perché il prestito è stato trattenuto in stdin?

Data la seguente funzione:

use std::io::{BufRead, stdin}; fn foo() -> usize { let stdin = stdin(); let stdinlock = stdin.lock(); stdinlock .lines() .count() } 

Questo non riesce a compilare con il seguente errore:

 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 

Trovo questo sorprendente perché il risultato di consumare il blocco (tramite lines ) non mantiene alcun riferimento alla fonte originale. In effetti, assegnare lo stesso risultato a un’associazione prima di tornare funziona perfettamente ( Playground ).

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

Questo suggerisce che restituire un “blocco consumato” ha immediatamente portato alla serratura il tentativo di vivere più a lungo del contenuto bloccato, molto in un modo insolito. Tutti i riferimenti che ho esaminato in genere indicano che l’ordine della dichiarazione è importante, ma non il modo in cui gli oggetti restituiti possono influire sull’ordine in cui vengono rilasciati.

Quindi, perché la funzione precedente è stata rifiutata dal compilatore? Perché la serratura sembra essere conservata più a lungo del previsto?

Questo sembra essere un bug nel compilatore. È ansible rendere il compilatore felice utilizzando un’istruzione di reso esplicita:

 use std::io::{stdin, BufRead}; fn foo() -> usize { let stdin = stdin(); let stdinlock = stdin.lock(); return stdinlock .lines() .count(); } fn main() {} 

terreno di gioco

Come menzionato nei commenti, ci sono più problemi di Rust relativi a questo:

  • 37407
  • 21114

Non posso rispondere al motivo della tua domanda, ma posso affermare che l’attuale implementazione 1 di vite non lessicali consente la compilazione del codice originale:

 #![feature(nll)] use std::io::{BufRead, stdin}; fn foo() -> usize { let stdin = stdin(); let stdinlock = stdin.lock(); stdinlock .lines() .count() } 

Terreno di gioco

1 1.25.0-nightly (2018-01-11 73ac5d6)