<commit_before>trait Alive {
    fn alive(&self);
}


// Obj: simple struct
// ////////////////////////////////////////////////////////

struct Obj {
    name: String,
}

impl Obj {
    fn new( name: &str ) -> Obj {
        let o = Obj{ name: name.to_string() };
        println!("+ Constructed Obj name={}", name);
        o
    }
}

impl Alive for Obj {
    fn alive(&self) {
        println!("= Obj name={} is alive", self.name);
    }
}

impl Drop for Obj {
    fn drop(&mut self) {
        println!("- Dropping Obj name={}", self.name);
    }
}

impl Clone for Obj {
    fn clone(&self) -> Self {
        Obj::new( &self.name[..] )
    }

    fn clone_from(&mut self, source: &Self) { 
        self.name = source.name.clone();
    }
}


// Obj: copyable struct
// ////////////////////////////////////////////////////////

#[derive(Copy, Clone)]
struct CopyObj {
    name: &'static str,
}

impl CopyObj {
    fn new( name: &'static str ) -> CopyObj {
        let o = CopyObj{ name: name };
        println!("+ Constructed CopyObj name={}", name);
        o
    }
}

impl Alive for CopyObj {
    fn alive(&self) {
        println!("= CopyObj name={} is alive", self.name);
    }
}

// Remarks: Drop cannot be implemented for "Copy" types.


// checking
// ////////////////////////////////////////////////////////


fn print_alive_by_ref<T: Alive>(o: &T) {
    println!("> enter print_alive_by_ref()");
    o.alive();
    println!("< exit print_alive_by_ref()");
}

fn print_alive_by_mut_ref<T: Alive>(o: &mut T) {
    println!("> enter print_alive_by_mut_ref()");
    o.alive();
    println!("< exit print_alive_by_mut_ref()");
}

fn print_alive_by_value<T: Alive>(o: T) {
    println!("> enter print_alive_by_value()");
    o.alive();
    println!("< exit print_alive_by_value()");
}



fn main() {
    println!("> enter main()");
    let mut o1 = Obj::new( "main" );
    o1.alive();
    print_alive_by_ref(&o1);
    print_alive_by_mut_ref(&mut o1);
    {
        let mut o1_clone = o1.clone();
        o1_clone.name = "main_clone".to_string();
        print_alive_by_value(o1); // pass by move semantic
        println!("returned from print_alive_by_value, o1 should have been destroyed");
        o1_clone.alive();
    }
    println!("exit sub-scope, o1_clone should have been destroyed");
    println!("");
    
    let mut o2 = CopyObj::new( "main_copyable" );
    o2.alive();
    print_alive_by_ref(&o2);
    print_alive_by_mut_ref(&mut o2);
    let mut o2_clone = o2.clone();
    o2_clone.name = "main_copyable_clone";
    print_alive_by_value(o2); // pass by copy semantic
    // because CopyObj implements the Copy trait, it can still be use
    o2.alive();
    o2_clone.alive();
    println!("");
    println!("< exit main()");
}<commit_msg>Added object address to trace to visualize "move"<commit_after>trait Alive {
    fn alive(&self);
}


// Obj: simple struct
// ////////////////////////////////////////////////////////

struct Obj {
    name: String,
}

impl Obj {
    fn new( name: &str ) -> Obj {
        let o = Obj{ name: name.to_string() };
        let ptr: *const Obj = &o;
        println!("+ Constructed Obj name={} @{:?}", name, ptr);
        o
    }
}

impl Alive for Obj {
    fn alive(&self) {
        let ptr: *const Obj = self;
        println!("= Obj name={} is alive @{:?}", self.name, ptr);
    }
}

impl Drop for Obj {
    fn drop(&mut self) {
        let ptr: *const Obj = self;
        println!("- Dropping Obj name={} @{:?}", self.name, ptr);
    }
}

impl Clone for Obj {
    fn clone(&self) -> Self {
        Obj::new( &self.name[..] )
    }

    fn clone_from(&mut self, source: &Self) { 
        self.name = source.name.clone();
    }
}


// Obj: copyable struct
// ////////////////////////////////////////////////////////

#[derive(Copy, Clone)]
struct CopyObj {
    name: &'static str,
}

impl CopyObj {
    fn new( name: &'static str ) -> CopyObj {
        let o = CopyObj{ name: name };
        let ptr: *const CopyObj = &o;
        println!("+ Constructed CopyObj name={} @{:?}", name, ptr);
        o
    }
}

impl Alive for CopyObj {
    fn alive(&self) {
        let ptr: *const CopyObj = self;
        println!("= CopyObj name={} is alive @{:?}", self.name, ptr);
    }
}

// Remarks: Drop cannot be implemented for "Copy" types.


// checking
// ////////////////////////////////////////////////////////


fn print_alive_by_ref<T: Alive>(o: &T) {
    println!("> enter print_alive_by_ref()");
    o.alive();
    println!("< exit print_alive_by_ref()");
}

fn print_alive_by_mut_ref<T: Alive>(o: &mut T) {
    println!("> enter print_alive_by_mut_ref()");
    o.alive();
    println!("< exit print_alive_by_mut_ref()");
}

fn print_alive_by_value<T: Alive>(o: T) {
    println!("> enter print_alive_by_value()");
    o.alive();
    println!("< exit print_alive_by_value()");
}



fn main() {
    println!("> enter main()");
    let mut o1 = Obj::new( "main" );
    o1.alive();
    print_alive_by_ref(&o1);
    print_alive_by_mut_ref(&mut o1);
    {
        let mut o1_clone = o1.clone();
        o1_clone.name = "main_clone".to_string();
        o1_clone.alive();
        print_alive_by_value(o1); // pass by move semantic
        println!("returned from print_alive_by_value, o1 should have been destroyed");
        o1_clone.alive();
    }
    println!("exit sub-scope, o1_clone should have been destroyed");
    println!("");
    
    let mut o2 = CopyObj::new( "main_copyable" );
    o2.alive();
    print_alive_by_ref(&o2);
    print_alive_by_mut_ref(&mut o2);
    let mut o2_clone = o2.clone();
    o2_clone.name = "main_copyable_clone";
    o2_clone.alive();
    print_alive_by_value(o2); // pass by copy semantic
    // because CopyObj implements the Copy trait, it can still be use
    o2.alive();
    o2_clone.alive();
    println!("");
    println!("< exit main()");
}
{'fraction_non_alphanumeric': 0.2133424798490825, 'fraction_numerical': 0.007545875493054364, 'mean_word_length': 2.1730141458106638, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5375672', 'n_tokens_mistral': 2080, 'n_tokens_neox': 2043, 'n_words': 505}