Por que o valor foi transferido para o fechamento aqui em vez de emprestado?

oCapítulo Tratamento de erros do livro Rust contém um exemplo de como usar os combinadores deOption eResult. Um arquivo é lido e, através da aplicação de uma série de combinadores, o conteúdo é analisado como umi32 e retornou em umResult<i32, String>. Agora, fiquei confuso quando olhei o código. Lá, em um fechamento para um e - em seguida, um localString é criado um valor passado posteriormente como um valor de retorno para outro combinador.

Aqui está o exemplo 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),
    }
}

O valor a que me refiro écontents. Ele é criado e posteriormente referenciado nomap combinador aplicado aostd::io::Result<usize> valor de retorno deRead::read_to_string. A pergunta: eu pensei quenão marcando o fechamento commove emprestaria qualquer valor referenciado por padrão, o que resultaria na reclamação do verificador de empréstimo, quecontents não vive o suficiente. No entanto, esse código compila perfeitamente. Isso significa que oString contents é movido para dentro e subseqüentemente fora do fechamento. Por que isso é feito sem o explícitomove?

questionAnswers(1)

yourAnswerToTheQuestion