2. Mozilla
The language grew out of a personal project by Mozilla employee Graydon Hoare.
Mozilla began sponsoring the project in 2009 and announced it in 2010. The same
year, work shifted from the initial compiler (written in OCaml) to the self-hosting
compiler written in Rust. Known as rustc, it successfully compiled itself in 2011.
rustc uses LLVM as its back end.
3. Safe, concurrent, practical language
Rust is a general-purpose, multi-paradigm, compiled programming language.
It is designed to be a "safe, concurrent, practical language", supporting pure-
functional, imperative-procedural, and object-oriented styles.
14. Functions
fn add_one(x: i32) -> i32 {
x + 1;
}
We would get an error:
error: not all control paths return a value
fn add_one(x: i32) -> i32 {
x + 1;
}
help: consider removing this semicolon:
x + 1;
^
16. Type inference
Rust has this thing called ‘type inference’. If it can figure out what the type of
something is, Rust doesn’t require you to actually type it out.
let x = 5; // x: i32
fn plus_one(i: i32) -> i32 {
i + 1
}
// without type inference
let f: fn(i32) -> i32 = plus_one;
// with type inference
let f = plus_one;
17. Mutability
let x = 5;
x = 10;
error: re-assignment of immutable variable `x`
x = 10;
^~~~~~~
22. fn divide(numerator: f64, denominator: f64) -> Result<f64, &'static str> {
if denominator == 0.0 {
Err("Can not divide by zero")
} else {
Ok(numerator / denominator)
}
}
Result
23. Pattern matching
let x = 5;
match x {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
4 => println!("four"),
5 => println!("five"),
_ => println!("something else"),
}
24. Pattern matching
One of the many advantages of match is it enforces ‘exhaustiveness checking’.
For example if we remove the last arm with the underscore _, the compiler will
give us an error:
error: non-exhaustive patterns: `_` not covered
25. Pattern matching
// The return value of the function is an option
let result = divide(2.0, 3.0);
// Pattern match to retrieve the value
match result {
// The division was valid
Some(x) => println!("Result: {}", x),
// The division was invalid
None => println!("Cannot divide by 0"),
}
26. Pattern matching
// The return value of the function is an Result<f64, &'static str>
let result = divide(2.0, 3.0);
// Pattern match to retrieve the value
match result {
// The division was valid
Ok(x) => println!("Result: {}", x),
// The division was invalid
Err(e) => println!(e),
}
27. Pattern matching
Again, the Rust compiler checks exhaustiveness, so it demands that you have a
match arm for every variant of the enum. If you leave one off, it will give you a
compile-time error unless you use _ or provide all possible arms.
32. The Stack
fn foo() {
let y = 5;
let z = 100;
}
fn main() {
let x = 42;
foo();
}
33. The Stack
fn foo() {
let y = 5;
let z = 100;
}
fn main() {
let x = 42; <-
foo();
}
Address Name Value
0 x 42
34. The Stack
fn foo() {
let y = 5;
let z = 100;
}
fn main() {
let x = 42;
foo(); <-
}
Address Name Value
2 z 1000
1 y 5
0 x 42
35. The Stack
fn foo() {
let y = 5;
let z = 100;
}
fn main() {
let x = 42;
foo();
} <-
Address Name Value
0 x 42
36. The Heap
fn main() {
let x = Box::new(5);
let y = 42;
}
Address Name Value
(230) - 1 5
... ... ...
1 y 42
0 x → (230) - 1
37. Ownership
let v = vec![1, 2, 3];
let v2 = v;
println!("v[0] is: {}", v[0]);
error: use of moved value: `v`
println!("v[0] is: {}", v[0]);
^
38. Ownership
fn take(v: Vec<i32>) {
// what happens here isn’t important.
}
let v = vec![1, 2, 3];
take(v);
println!("v[0] is: {}", v[0]);
Same error: ‘use of moved value’.
39. Borrowing
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);
40. Borrowing
fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
// do stuff with v1 and v2
// return the answer
42
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let answer = foo(&v1, &v2);
// we can use v1 and v2 here!
41. &mut references
fn foo(v: &Vec<i32>) {
v.push(5);
}
let v = vec![];
foo(&v);
errors with:
error: cannot borrow immutable borrowed content `*v` as mutable
v.push(5);
^
43. The Rules
First, any borrow must last for a scope no greater than that of the owner. Second,
you may have one or the other of these two kinds of borrows, but not both at the
same time:
one or more references (&T) to a resource,
exactly one mutable reference (&mut T).
44. Rust prevents data races at compile time
There is a ‘data race’ when two or more pointers access the same memory
location at the same time, where at least one of them is writing, and the operations
are not synchronized.
45. Lifetimes
1. I acquire a handle to some kind of resource.
2. I lend you a reference to the resource.
3. I decide I’m done with the resource, and deallocate it, while you still have your
reference.
4. You decide to use the resource.
48. Lifetimes
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let y = &5; // this is the same as `let _y = 5; let y = &_y;`
let f = Foo { x: y };
println!("{}", f.x);
}
49. Lifetimes
We need to ensure that any reference to a Foo cannot outlive the reference to an
i32 it contains.
50. Thinking in scopes
fn main() {
let y = &5; // -+ y goes into scope
// |
// stuff // |
// |
} // -+ y goes out of scope
51. Thinking in scopes
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let y = &5; // -+ y goes into scope
let f = Foo { x: y }; // -+ f goes into scope
// stuff // |
// |
} // -+ f and y go out of scope
52. Thinking in scopes
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let x; // -+ x goes into scope
// |
{ // |
let y = &5; // ---+ y goes into scope
let f = Foo { x: y }; // ---+ f goes into scope
x = &f.x; // | | error here
} // ---+ f and y go out of scope
// |
println!("{}", x); // |
} // -+ x goes out of scope
54. Resources
The Rust Programming Language. Also known as “The Book”, The Rust Programming Language is the
most comprehensive resource for all topics related to Rust, and is the primary official document of the
language.
Rust by Example. A collection of self-contained Rust examples on a variety of topics, executable in-
browser.
Frequently asked questions.
The Rustonomicon. An entire book dedicated to explaining how to write unsafe Rust code. It is for
advanced Rust programmers.
rust-learning. A community-maintained collection of resources for learning Rust.