fn main() { let s1 = String::from("hello"); // s1 owns the data "hello" println!("s1: {}", s1); let s2 = s1; // s1 is moved to s2. s1 is now invalid. // println!("s1 after move: {}", s1); // This would cause a compile-time error! println!("s2 after move: {}", s2); let s3 = &s2; // s3 immutably borrows from s2. // s2 can still be used, but cannot be mutated while s3 exists. println!("s3 (borrow of s2): {}", s3); println!("s2 (still valid after borrow): {}", s2); let mut s4 = String::from("world"); borrow_and_print(&s4); // Immutable borrow mutate_string(&mut s4); // Mutable borrow println!("s4 after mutation: {}", s4); } fn borrow_and_print(some_string: &String) { println!("Borrowed string: {}", some_string); } fn mutate_string(some_string: &mut String) { some_string.push_str("!"); }