Println! prendere in prestito o possedere la variabile?

Sono confuso con il prestito e la proprietà. Nella documentazione di Rust su riferimento e prestito

let mut x = 5; { let y = &mut x; *y += 1; } println!("{}", x); 

Dicono

println! può prendere in prestito x .

Sono confuso da questo. Se println! prende in prestito x , perché passa ‘x’ non ‘& x’?

Provo a eseguire questo codice qui sotto

 fn main() { let mut x = 5; { let y = &mut x; *y += 1; } println!("{}", &x); } 

Questo codice è identico al codice sopra, tranne che passo ‘& x’ a println! . Stampa “6” sulla console che è corretta ed è lo stesso risultato del primo codice.

La print! macro print! , println! , eprint! , eprintln! , write! , writeln! e format! sono un caso speciale, non comportarsi come fanno le cose normali per ragioni di convenienza. Il fatto che prendano riferimenti in silenzio fa parte di questa differenza.

 fn main() { let x = 5; println!("{}", x); } 

rustc -Z unstable-options --pretty expanded attraverso rustc -Z unstable-options --pretty expanded nel compilatore notturno e possiamo vedere cosa println! si espande a:

 #![feature(prelude_import)] #![no_std] #[prelude_import] use std::prelude::v1::*; #[macro_use] extern crate std as std; fn main() { let x = 5; ::io::_print(::std::fmt::Arguments::new_v1( { static __STATIC_FMTSTR: &'static [&'static str] = &["", "\n"]; __STATIC_FMTSTR }, &match (&x,) { (__arg0,) => { [ ::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt), ] } }, )); } 

Riordinato molto, è questo:

 use std::fmt; use std::io; fn main() { let x = 5; io::_print(fmt::Arguments::new_v1( &["", "\n"]; &[fmt::ArgumentV1::new(&x, fmt::Display::fmt)], )); } 

Nota il &x .

Se scrivi println!("{}", &x) , hai a che fare con due livelli di riferimenti; questo ha lo stesso risultato perché c’è un’implementazione di std::fmt::Display per &T dove T implementa Display (mostrato come impl<'a, T> Display for &'a T where T: Display + ?Sized ) che solo passa attraverso Potresti anche scrivere &&&&&&&&&&&&&&&&&&&&&&&x .