¿Por qué el valor se traslada al cierre aquí en lugar de ser prestado?

losCapítulo de manejo de errores del Rust Book contiene un ejemplo sobre cómo usar los combinadores deOption yResult. Se lee un archivo y, mediante la aplicación de una serie de combinadores, los contenidos se analizan comoi32 y regresó en unResult<i32, String>. Ahora, me confundí cuando miré el código. Allí, en un cierre a un y luego un localString Se crea un valor que luego se pasa como valor de retorno a otro combinador.

Aquí está el ejemplo de código:

use std::fs::File;
use std::io::Read;
use std::path::Path;

fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
    File::open(file_path)
         .map_err(|err| err.to_string())
         .and_then(|mut file| {
              let mut contents = String::new(); // local value
              file.read_to_string(&mut contents)
                  .map_err(|err| err.to_string())
                  .map(|_| contents) // moved without 'move'
         })
         .and_then(|contents| {
              contents.trim().parse::<i32>()
                      .map_err(|err| err.to_string())
         })
         .map(|n| 2 * n)
}

fn main() {
    match file_double("foobar") {
        Ok(n) => println!("{}", n),
        Err(err) => println!("Error: {}", err),
    }
}

El valor al que me refiero escontents. Se crea y luego se hace referencia en elmap combinador aplicado a lastd::io::Result<usize> valor de retorno deRead::read_to_string. La pregunta: pensé queno marcando el cierre conmove tomaría prestado cualquier valor referenciado por defecto, lo que resultaría en que el verificador de préstamos se queje, quecontents no vive lo suficiente Sin embargo, este código se compila muy bien. Eso significa que elString contents se mueve dentro, y con frecuencia fuera del cierre. ¿Por qué se hace esto sin lo explícito?move?

Respuestas a la pregunta(1)

Su respuesta a la pregunta