rust - tengo - prestamos estudiantiles en estados unidos
Cuando se devuelve el resultado de consumir un StdinLock, ¿por qué se retuvo el préstamo a stdin? (2)
Dada la siguiente función:
use std::io::{BufRead, stdin};
fn foo() -> usize {
let stdin = stdin();
let stdinlock = stdin.lock();
stdinlock
.lines()
.count()
}
Esto no se compila con el siguiente 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
Me parece sorprendente porque el resultado de consumir el bloqueo (a través de lines
) no conserva ninguna referencia a la fuente original. De hecho, asignar el mismo resultado a un enlace antes de regresar funciona bien ( Playground ).
fn bar() -> usize {
let stdin = stdin();
let stdinlock = stdin.lock();
let r = stdinlock
.lines()
.count();
r
}
Esto sugiere que devolver un "bloqueo consumido" inmediatamente ha llevado a que el bloqueo intente vivir más tiempo que el contenido bloqueado, mucho de una manera inusual. Todas las referencias que busqué generalmente indican que el orden de la declaración es importante, pero no cómo los objetos devueltos pueden afectar el orden en que se liberan.
Entonces, ¿por qué la compilación rechaza la función anterior? ¿Por qué aparentemente se retiene la cerradura durante más tiempo del esperado?
Esto parece ser un error en el compilador. Puedes hacer feliz al compilador usando una declaración de return
explícita:
use std::io::{stdin, BufRead};
fn foo() -> usize {
let stdin = stdin();
let stdinlock = stdin.lock();
return stdinlock
.lines()
.count();
}
fn main() {}
Como se mencionó en los comentarios, hay varios problemas de Rust relacionados con esto:
No puedo responder el porqué de su pregunta, pero puedo afirmar que la implementación actual de tiempos de vida no léxicos permite que el código original se compile:
#![feature(nll)]
use std::io::{BufRead, stdin};
fn foo() -> usize {
let stdin = stdin();
let stdinlock = stdin.lock();
stdinlock
.lines()
.count()
}
1 1.25.0 por noche (2018-01-11 73ac5d6)