From 1b1274ff90a816aeb76752df1c0f5a56eb76ea0a Mon Sep 17 00:00:00 2001 From: Rowan Torbitzky-Lane Date: Wed, 19 Mar 2025 03:04:50 -0500 Subject: [PATCH] start going through ch4 --- ch4/ownership/Cargo.lock | 7 ++++ ch4/ownership/Cargo.toml | 6 ++++ ch4/ownership/src/main.rs | 69 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 ch4/ownership/Cargo.lock create mode 100644 ch4/ownership/Cargo.toml create mode 100644 ch4/ownership/src/main.rs diff --git a/ch4/ownership/Cargo.lock b/ch4/ownership/Cargo.lock new file mode 100644 index 0000000..21b71f8 --- /dev/null +++ b/ch4/ownership/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ownership" +version = "0.1.0" diff --git a/ch4/ownership/Cargo.toml b/ch4/ownership/Cargo.toml new file mode 100644 index 0000000..e884752 --- /dev/null +++ b/ch4/ownership/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "ownership" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/ch4/ownership/src/main.rs b/ch4/ownership/src/main.rs new file mode 100644 index 0000000..7a453c9 --- /dev/null +++ b/ch4/ownership/src/main.rs @@ -0,0 +1,69 @@ +fn read(y: bool) { + if y { + println!("y is true!"); + } +} + +// Rust wants to ensure no undefined behavior at compile-time +// Sounds a lot like Haskell! +fn main() { + // read(x); // Moving read here would cause an error + let x = true; + read(x); + + // ------------------------------------------------------------- + // How variable live in the stack + + let n = 5; // step 1: stack stores n = 5 + let y = plus_one(n); // step 3: stack stores n = 5 and y = 6 now + println!("The value of y is: {y}"); + + // These variables live in frames + // The frame for main at step 1 holds n = 5 + // Frame for plus_one at step 2 holds x = 5 + // Frame for main at step 3 holds n = 5 and y = 6 + // + // These frames get organized into a stack of currently-called-functions. + // At step 2, the frame for main sits above the frame for the called function, plus_one. + // + // For Rust to transfer access to data without copying it, it uses pointers. + // Pointers and pointees + // Rust can put data on the heap with Box. + // The stack holds data associated with specific functions while + // the heap holds data that can outlive a function. + + // There is only one array in memory at a time with this method. + let a = Box::new([0; 1_000_000]); + let b = a; + // println!("first value of a {}", a[0]); // This code is invalid bc of borrowing from a + + // Rust doesn't allow user memory management + + // ------------------------------------------------------------- + // Box's owner manages deallocation + + // Almost how this works: + // When a variable is bound to a box, when Rust deallocates the variable's + // frame, then Rust deallocates the box's heap memory. + let a_num = 4; + make_and_drop(); + + // How this works fully (uses ownership): + // When variable owns a box, when Rust deallocates the variable's frame, + // then Rust deallocates the box's heap memory. + let d = Box::new([0; 1_000_000]); // d owns this Box here + let e = d; // e has ownership of the box transfered to it from d + + // Rust data structures like String, Vec, and HashMap use Boxes. + + // Stopped here for the night: + // https://rust-book.cs.brown.edu/ch04-01-what-is-ownership.html#variables-cannot-be-used-after-being-moved +} + +fn plus_one(x: i32) -> i32 { + x + 1 // step 2: stack stores n = 5 from main and x = 5 in this function +} + +fn make_and_drop() { + let a_box = Box::new(5); +}