Challenge 2: Why i32 Copies But String Moves — Possible Solution ==================================================================== let x = 5; let y = x; println!("{} {}", x, y); compiles fine because i32 implements Rust's Copy trait. i32 is a simple, fixed-size value that lives entirely on the stack — copying it is just duplicating a small, fixed number of bytes, which is so cheap that Rust performs this copy AUTOMATICALLY on assignment rather than moving ownership. Because a genuine copy was made, x and y are two completely independent i32 values from that point on — neither one is invalidated, and both can be used (including inside the same println!) without any compiler objection. The equivalent pattern with a String does NOT compile because String does NOT implement Copy — it manages heap-allocated data (its actual character content lives on the heap, with only a pointer/length/ capacity on the stack). Per this chapter's move semantics, assigning one String variable to another MOVES ownership of that heap data rather than copying it, specifically because a String's data could be arbitrarily large, and Rust never performs an expensive, potentially large copy implicitly — only cheap, fixed-size Copy types get that automatic-copy treatment. Since the original String variable is moved (not copied), it becomes invalid, and referencing it afterward is a compile error — the exact opposite outcome of the i32 example, for precisely the reason that i32 is Copy and String is not.