A Brief Introduction to Rust
A language empowering everyone to build reliable and efficient software.
fn main() {
let mut sum: i64 = 0;
for i in 1..10 {
if i % 2 == 0 {
sum += i;
}
}
println!("sum is {}", sum);
}
fn main() {
let sum: i64 = (1..10).filter(|i| i % 2 == 0).sum();
println!("sum is {}", sum);
}
int overflow, buffer over-read, buffer overflow...
Rust: runtime bound check
Rust: Ownership + Borrowing (compiletime check)
A data race is any unsynchronized, concurrent access to data involving a write
Rust: Ownership + Borrowing (compiletime check)
Let's look at some book examples!
Owning the Book
struct Book;
fn john() {
let book = Book; // john owns the book
} // john destroys his book
struct Book;
fn steve() {
let book = Book; // steve owns the book
sally(book); // steve gives the book to sally
}
fn sally(book) {
// sally owns the book
} // sally destroys her book
Borrowing the Book
fn my() {
let mut book = Book;
spelling_corrector(&mut book);
// we must explicitly mention that we lend the book
// and we don't give it away
reader(&book);
}
fn spelling_corrector(book: &mut Book) {
// correct spelling in place
}
fn reader(book: &Book) {
// read a book
}
fn main() {
let mut v = vec![0; 2];
for _each in v.iter() {
v.push(1); // ?
}
println!("{:?}", v);
}
error[E0502]: cannot borrow `v` as mutable because
it is also borrowed as immutable
--> src/main.rs:4:9
|
3 | for _each in v.iter() {
| --------
| |
| immutable borrow occurs here
| immutable borrow later used here
4 | v.push(1); // ?
| ^^^^^^^^^ mutable borrow occurs here
{
let r; // ---------+-- 'a
{ // |
let x = 5; // -+-- 'b |
r = &x; // | |
} // -+ |
println!("r: {}", r); // |
} // ---------+
error[E0597]: `x` does not live long enough
--> src/main.rs:6:9
|
6 | r = &x;
| ^^^^^^ borrowed value does not live long enough
7 | }
| - `x` dropped here while still borrowed
8 |
9 | println!("r: {}", r);
| - borrow later used here
{
let x = 5; // ----------+-- 'b
// |
let r = &x; // --+-- 'a |
// | |
println!("r: {}", r); // | |
// --+ |
} // ----------+
(correct)
The compiler checks references are valid w.r.t referenced values lifetimes
Rust ownership ⇒ thread-safety
use std::thread;
fn main() {
let mut v = vec![];
thread::spawn(move || { // v is moved into closure
v.push(2);
});
v.push(3);
// ^ value borrowed here after move
}
use std::thread;
// A thread-safe reference-counting pointer
use std::sync::Arc;
fn main() {
let v = Arc::new(vec![1, 2, 3]);
let v2 = v.clone();
let child = thread::spawn(move || {
println!("{:?}", v2);
});
child.join().expect("child thread error");
println!("{:?}", v);
}
(correct)
use std::sync::Arc;
fn main() {
let mut v = Arc::new(vec![1, 2, 3]);
v.push(42);
// ^ cannot borrow data in an Arc as mutable
}
use std::thread;
use std::sync::{Arc, Mutex};
fn main() {
let v = Arc::new(Mutex::new(vec![1, 2, 3]));
let v2 = v.clone();
let child = thread::spawn(move || {
let mut vector = v2.lock().unwrap();
vector.push(4);
});
child.join().expect("child thread error");
println!("{}", v.lock().unwrap().len());
}
(correct)
References
these slides are made with reveal.js
Here be (owned) books (article by hauleth)
Illustrations