Lecture Note 4
Type checking memory safety in Rust
Transferring ownership
let p = Box::new(42i32);
//case 1
let q = p;
// p is moved to q;
// q will be reclaimed (freed) after the scoped defined
//case 2
foo(p);
// function call receives the ownership of p
Borrowed type
- Immutable + Full sharing
let s1 = String::from("hello"); //ownership
let s2 = calculate_length(&s1);
println!("The length of `{}` is {}.", s1, len);
fn calculate_length(s: &String) -> usize {
s.len() // why safe?: &String type ensures that s is immutable
}
// function signature
// pub fn len(&self) -> usize
// pub fn make_ascii_uppercase(&mut self)
Ensuring pointer validity
- Using after free ```rust let p = Box::new(42i32); let x = &p; drop(p);
*x; // error!
- Dangling pointer
```rust
fn dangle() -> &String {
let f = String::from("");
&f
} // freed when the scope ends; f is dropped
Mutably borrowed type
- Mutable + sharing
fn change(mut some_string: String) -> String { some_string.push_str(" "); some_string } // mutable borrow sanitizes this code fn change(mut some_string: &mut String) { some_string.push_str(" "); //ok } // function call let mut s: String = String::from("hello"); change(&mut s);Alias(borrow) XOR Mutation
- mutating object with immutable borrow is prohibited.
- mutation is ok if there is only no borrows
What Rust prevents
g = lock(); // -- p = &g.data; // | lifetime of g // | : critical section drop(g); // -- do_something(*p) // rust compiler rejects this code
- Some more programming features
- slices and structs
- smart pointers
- first-class functions
- parallel programming
- lifetime-wise: lock > lockguard > data inside ```rust // api.rs:109
pub struct LockGuard<’s, L: RawLock, T> {
lock: &’s Lock<L, T>,
// lifetime(lock) > lifetime(lockguard)
token: ManuallyDrop<L::Token>,
}
```