diff --git a/src/SUMMARY.md b/src/SUMMARY.md index fb02af6e..984dfbd9 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -57,6 +57,7 @@ - [Exclusive References](references/exclusive.md) - [Slices](references/slices.md) - [Strings](references/strings.md) + - [Reference Validity](references/dangling.md) - [Exercise: Geometry](references/exercise.md) - [Solution](references/solution.md) - [User-Defined Types](user-defined-types.md) diff --git a/src/borrowing/borrowck.md b/src/borrowing/borrowck.md index d84fe221..871321bb 100644 --- a/src/borrowing/borrowck.md +++ b/src/borrowing/borrowck.md @@ -4,8 +4,23 @@ minutes: 10 # Borrow Checking -Rust's _borrow checker_ puts constraints on the ways you can borrow values. For -a given value, at any time: +Rust's _borrow checker_ puts constraints on the ways you can borrow values. +We've already seen that a reference cannot _outlive_ the value it borrows: + + + +```rust,editable,compile_fail +fn main() { + let x_ref = { + let x = 10; + &x + }; + println!("x: {x_ref}"); +} +``` + +There's also a second main rule that the borrow checker enforces: The _aliasing_ +rule. For a given value, at any time: - You can have one or more shared references to the value, _or_ - You can have exactly one exclusive reference to the value. @@ -29,6 +44,9 @@ fn main() {
+- The "outlives" rule was demonstrated previously when we first looked at + references. We review it here to show students that the borrow checking is + following a few different rules to validate borrowing. - Note that the requirement is that conflicting references not _exist_ at the same point. It does not matter where the reference is dereferenced. - The above code does not compile because `a` is borrowed as mutable (through diff --git a/src/references/dangling.md b/src/references/dangling.md new file mode 100644 index 00000000..73680b48 --- /dev/null +++ b/src/references/dangling.md @@ -0,0 +1,39 @@ +--- +minutes: 3 +--- + +# Reference Validity + +Rust enforces a number of rules for references that make them always safe to +use. One rule is that references can never be `null`, making them safe to use +without `null` checks. The other rule we'll look at for now is that references +can't _outlive_ the data they point to. + + + +```rust,editable,compile_fail +fn main() { + let x_ref = { + let x = 10; + &x + }; + println!("x: {x_ref}"); +} +``` + +
+ +- This slide gets students thinking about references as not simply being + pointers, since Rust has different rules for references than other languages. + +- We'll look at the rest of Rust's borrowing rules on day 3 when we talk about + Rust's ownership system. + +## More to Explore + +- Rust's equivalent of nullability is the `Option` type, which can be used to + make any type "nullable" (not just references/pointers). We haven't yet + introduced enums or pattern matching, though, so try not to go into too much + detail about this here. + +
diff --git a/src/references/exclusive.md b/src/references/exclusive.md index 5f459828..93084f74 100644 --- a/src/references/exclusive.md +++ b/src/references/exclusive.md @@ -1,5 +1,5 @@ --- -minutes: 10 +minutes: 7 --- # Exclusive References diff --git a/src/references/shared.md b/src/references/shared.md index 2fa0c846..661a8d98 100644 --- a/src/references/shared.md +++ b/src/references/shared.md @@ -25,17 +25,6 @@ A shared reference to a type `T` has type `&T`. A reference value is made with the `&` operator. The `*` operator "dereferences" a reference, yielding its value. -Rust will statically forbid dangling references: - - - -```rust,editable,compile_fail -fn x_axis(x: &i32) -> &(i32, i32) { - let point = (*x, 0); - return &point; -} -``` -
- References can never be null in Rust, so null checking is not necessary.