Why does the Ownership of the non-copy type variables, does not get moved in the println! macro?

Facts That I Know:

Normally, the non-copy types like String, Vec, etc. have the concept of ownership being moved, when it is passed as a parameter to the functions/methods, or just assigned normally to other variables.

My Questions : :question:

  1. Why is it so that when I pass the similar non-copy types to println! or similar macros, it does not move the ownership of that variable, and we can use them even after println! statements ??
fn main() {
    let str: String = String::from("hello, world");
    println!("String: \"{}\"", str);
    println!("\nThis print also works, even when the str has been passed to println! before:\nString: \"{}\"", str);
  1. Is this behavior also prevalent in other std library macros like write!, or format! ?? :thinking:

Please note that I have just begun learning Rust, so mind me if I have asked silly question out of curiousity, and I would be really grateful if I get help on this doubt..

Thank you in advance for your time and efforts in solving my queries.. :blush:

It is because the macro expands to something containing &str rather than a bare str. The ampersand prevents it from being moved. All macros that perform formatting work like this, so yes, this is also the case for write! and format!.


So, the below code works fine with write! macro too:

use std::fmt;

struct Point(String, i32, i32);

impl fmt::Display for Point{
    fn fmt(self: &Self, f: &mut fmt::Formatter) -> fmt::Result{
        write!(f, "Point Name: {}, x: {}, y: {}", self.0, self.1, self.2)

fn main(){
    let p = Point(String::from("p1"),2,3);
    println!("{}", p);
    println!("{}", p.0);

Thank you for the help!!