3. Why Another Programming
Language?
Memory safe without garbage collection
Compiled language. Blazingly fast!
Makes concurrency easy...ier
Tough but very kind compiler
4. Memory safety? How unsafe could
it be?
Accessing uninitialized data
Dangling pointers
Double free
Data races
5. Memory safety? How unsafe could
it be?
Accessing uninitialized data
Dangling pointers
Double free
Data races
Shared mutable state is the root of all
7. Ownership
Variable Bindings have the ownership of what
they bound to
fn foo() {
// v is the owner of the vector!
let v = vec![1, 2, 3];
}
8. Ownership
Ownership could be transfered
fn main() {
// v is the owner of the vector
let v = vec![1, 2, 3];
// Not anymore. The ownership has been transfered
// to i_want_v
let i_want_v = v;
println!("{}", v[0]); // Error!!!!
}
9. Ownership
Pass-by-Value is Pass-the-Ownership
fn take_ownership(v: Vec<i32>) {
println!("I got the ownership!!!");
}
fn main() {
// v is the owner of the vector
let v = vec![1, 2, 3];
// Now pass the ownership to take_ownership
take_ownership(v);
println!("{}", v[0]); // Error!!!!
}
10. Ownership
Pass-by-Value is Pass-the-Ownership
fn take_ownership(v: Vec<i32>) {
println!("I got the ownership!!!");
}
fn main() {
// v is the owner of the vector
let v = vec![1, 2, 3];
// Now pass the ownership to take_ownership
take_ownership(v);
println!("{}", v[0]); // Error!!!!
}
Unless you got Copy trait.
11. Ownership
Why so serious, compiler?
What if we don't care about ownership?
let v = vec![1, 2, 3];
let mut v2 = v;
v2.truncate(2); // Shorten the length to 2 elements long
println!("Let me access v[2]...{}", v[2]) // Error!!
13. Ownership
Why so serious, compiler?
Because we have stack and heap
Shared and mutable state is the root of all
14. Ownership
Why so serious, compiler?
Because we have stack and heap
Shared and mutable state is the root of all
15. Ownership
"Hey foo, I need that ownership back."
"Ok then."
fn foo(v1: Vec<i32>, v2: Vec<i32>)
-> (Vec<i32>, Vec<i32>, i32) {
// do stuff with v1 and v2...
// hand back ownership and the result of our function
(v1, v2, 42)
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let (v1, v2, answer) = foo(v1, v2);
16. References And Borrowing
The resources could be borrowed!
Borrowed by references
Shared Reference
Mutable Reference
17. References And Borrowing
Shared Reference &T
fn sum_vec(v: &Vec<i32>) -> i32 {
// Borrow a shared reference of a vector and
// calculating sum of all elements
return v.iter().fold(0, |a, &b| a + b);
}
fn main() {
let v = vec![1, 2, 3, 4];
let sum = sum_vec(&v);
println!("Sum of {:?} is {}", v, sum); // No Error!
}
18. References And Borrowing
Mutable Reference &mut T
fn add_element(v: &mut Vec<i32>, value: i32) {
v.push(value); // Mutate the vector
}
fn main() {
let mut v = vec![1, 2, 3, 4]; // mut is needed
add_element(&mut v, 5); // Borrowed as mutable
}
19. References And Borrowing
let mut v = vec![1, 2, 3];
let v2 = &mut v;
v2.truncate(2);
// Oh no! v doesn't know the referenced vector
// has changed!
println!("Let me access v[2]...{}", v[2]);
20. References And Borrowing
let mut v = vec![1, 2, 3];
let v2 = &mut v;
v2.truncate(2);
// Oh no! v doesn't know the referenced vector
// has changed!
println!("Let me access v[2]...{}", v[2]);
error: cannot borrow `v` as immutable because
it is also borrowed as mutable
21. References And Borrowing
The Rules
1. Any borrow must last for a scope no greater than
that of the owner.
2. Either one of the following, but not both at the
same time:
One or more references ( &T ) to the resource
Exactly one mutable reference ( &mut T ) to the
resource
22. References And Borrowing
The Rules
1. Any borrow must last for a scope no greater than
that of the owner.
2. Either one of the following, but not both at the
same time:
One or more references ( &T ) to the resource
Exactly one mutable reference ( &mut T ) to the
resource
Shared and mutable state is the root of all
23. References And Borrowing
The Rules
1. Any borrow must last for a scope no greater than
that of the owner.
2. Either one of the following, but not both at the
same time:
One or more references ( &T ) to the resource
Exactly one mutable reference ( &mut T ) to the
resource
Shared and mutable state is the root of all
24. References And Borrowing
The Rules
1. Any borrow must last for a scope no greater than
that of the owner.
2. Either one of the following, but not both at the
same time:
One or more references ( &T ) to the resource
Exactly one mutable reference ( &mut T ) to the
resource
Shared and mutable state is the root of all
26. References And Borrowing
Why so serious, compiler?
Iterator Invalidation ex. 1
let mut v = vec![1, 2, 3];
for i in &v {
println!("{}", i);
v.push(34); // Might be reallocated!!
}
27. References And Borrowing
Why so serious, compiler?
Iterator Invalidation ex. 1
let mut v = vec![1, 2, 3];
for i in &v {
println!("{}", i);
v.push(34); // Might be reallocated!!
}
error: cannot borrow `v` as mutable because it is also
borrowed as immutable
v.push(34);
^
28. References And Borrowing
Why so serious, compiler?
Iterator Invalidation ex. 2
// Copy elements to another vector
fn append_vec(from: &Vec<i32>, to: mut &Vec<i32>) {
for elem in from.iter() {
to.push(*elem);
}
}
29. References And Borrowing
Why so serious, compiler?
Iterator Invalidation ex. 2
// What if from and to are the same?
fn append_vec(from: &Vec<i32>, to: mut &Vec<i32>) {
for elem in from.iter() {
to.push(*elem);
}
}
30. References And Borrowing
Why so serious, compiler?
Iterator Invalidation ex. 2
// Dangling pointer!!!!
fn append_vec(from: &Vec<i32>, to: mut &Vec<i32>) {
for elem in from.iter() {
to.push(*elem); // Might be reallocated!!
}
}
31. References And Borrowing
Why so serious, compiler?
Iterator Invalidation ex. 2
// Dangling pointer!!!!
fn append_vec(from: &Vec<i32>, to: mut &Vec<i32>) {
for elem in from.iter() {
to.push(*elem); // Might be reallocated!!
}
}
error: cannot borrow `new_v` as mutable because it is also
borrowed as immutable
// Whew~
32. References And Borrowing
Why so serious, compiler?
Use after free
fn main() {
let y: &i32;
{
let x = 5;
y = &x; // borrow a reference from x
} // Oh no! x died! what is y now!?
println!("{}", y);
}
33. References And Borrowing
Why so serious, compiler?
Use after free
fn main() {
let y: &i32;
{
let x = 5;
y = &x; // borrow a reference from x
} // Oh no! x died! what is y now!?
println!("{}", y);
}
error: `x` does not live long enough
y = &x;
^
36. Conclusions
Rust combines high-level features with low-level
control
Rust gives strong safety guarantees beyond what
GC can offer:
Deterministic destruction
Data race freedom
Iterator Invalidation