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!.

4 Likes

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

use std::fmt;

#[derive(Debug)]
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!!