Briefly Rust
Daniele Esposti
@expobrain
Rust
● Static typed
● Compiled ahead of time
● Memory safety without Garbage Collector
● Abstractions without overhead
Rust
Project internally started
by Mozilla’s employee in
the 2009
First pre-alpha release
in January 2012
First stable release 1.0
on May 2015
Currently, July 2016,
at version 1.9
The aim of the language
is to be as fast as C/C++
but safer
and more expressive
Why the name “Rust”
Rust
Graydon Hoare, the
creator of the language,
named it after a fungus
Meet the language
Hello World
fn main() {
let x = 42;
println!("Hello, world {}!", x);
}
Pure functions, and variables are not-mutable by default
Enums
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
Enumerators can have optional associated data
Pattern Matching
fn quit() { /* ... */ }
fn change_color(r: i32, g: i32, b: i32) { /* ... */ }
fn move_cursor(x: i32, y: i32) { /* ... */ }
fn process_message(msg: Message) {
match msg {
Message::Quit => quit(),
Message::ChangeColor(r, g, b) => change_color(r, g, b),
Message::Move { x: x, y: y } => move_cursor(x, y),
Message::Write(s) => println!("{}", s),
};
}
Similar to switch case but more flexible on the matching
Pattern Matching
let x = '💅';
let y = 1;
match x {
'a' ... 'j' => println!("early letter"),
'k' ... 'z' => println!("late letter"),
_ => println!("something else"),
}
match y {
1 ... 5 => println!("one through five"),
_ => println!("anything"),
}
...Like those examples
Structs
struct Point {
x: i32,
y: i32,
}
fn main() {
let origin = Point { x: 0, y: 0 }; // origin: Point
println!("The origin is at ({}, {})", origin.x, origin.y);
}
Can have methods or Traits
Methods
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
fn main() {
let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
println!("{}", c.area());
}
Methods are just functions attached to a struct
Traits
struct Circle {
x: f64,
y: f64,
radius: f64,
}
trait HasArea {
fn area(&self) -> f64;
}
impl HasArea for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
Traits are like interfaces; combine traits for polymorphism
Iterators
(1..)
.filter(|&x| x % 2 == 0)
.filter(|&x| x % 3 == 0)
.take(5)
.collect::<Vec<i32>>();
Iterators help to build solutions with functional programming
Functional programming is integrated within the language
Memory Safety
without
Garbage Collector
Ownership / 1
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]);
You cannot use a value owned by someone else
The compiler will throw an error for you
Ownership / 2
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]);
error: use of moved value: `v`
println!("v[0] is: {}", v[0]);
^
Passing by value move the ownership as well
Borrowing / 1
fn foo(v: &Vec<i32>) -> i32 {
// do stuff with v
}
let v = vec![1, 2, 3];
foo(&v);
println!("v[0] is: {}", v[0]); // it works
Avoid moving ownership by passing by reference
References are immutable
Borrowing / 2
fn bar(v: &mut Vec<i32>) {
v.push(4)
}
let mut v = vec![1, 2, 3];
bar(v);
println!("{:?}", v[0]); // [1, 2, 3, 4]
Mutable references allows you to mutate the borrowed one
Lifetimes / 1
struct Child {}
struct Parent {
child: &Child
}
let child = Child{};
let parent = Parent{child: &child};
error: missing lifetime specifier [E0106]
child: &Child
^~~~~~
Problem, when child goes out of scope parent will point
to freed memory
Lifetimes / 2
struct Child {}
struct Parent<'a> {
child: &'a Child
}
let child = Child{};
let parent = Parent{child: &child};
We declare a lifetime ‘a, the compiler will free the memory
of child when Parent’s memory is freed
Abstraction
without
overhead
Compilation
Language is translated into MIR
and then compiled with LLVM
Rust MIR LLVM ASM
● Desugaring
● Reduce Rust to a simple core
● Create a control flow graph
● Simplify match expression, apply explicit drops and panics
● Output LLVM IR
Optimisations
MIR: mid-level IR
MIR / 1
Simple Rust code...
for elem in vec {
process(elem);
}
MIR / 2
...converted into partial MIR
let mut iterator = IntoIterator::into_iter(vec);
loop:
match Iterator::next(&mut iterator) {
Some(elem) => { process(elem); goto loop; }
None => { goto break; }
}
break:
...
LLVM
● Applies 100+ between transformations and optimisations
● Link-time optimisations
● Target multiple platforms: x86, ARM, WebAssembly
Final binary
● The final binary is statically compiled
● No need of pre-installed runtime
● Only system provided libraries are linked
Final binary
https://github.com/brson/httptest compiled on macOS
10.15 with cargo build --release
$ otool -L target/release/httptest
target/release/httptest:
/usr/lib/libssl.0.9.8.dylib
/usr/lib/libcrypto.0.9.8.dylib
/usr/lib/libSystem.B.dylib
References
● Internet archaeology: the definitive, end-all source for why Rust
is named "Rust"
(https://www.reddit.com/r/rust/comments/27jvdt/internet_archae
ology_the_definitive_endall_source/)
● Introducing MIR (http://blog.rust-lang.org/2016/04/19/MIR.html)
● Introduce a "mid-level IR" (MIR) into the compiler
(https://github.com/nikomatsakis/rfcs/blob/mir/text/0000-mir.md)
Thank you!
@expobrain
https://techblog.badoo.com/

Briefly Rust

  • 1.
  • 2.
    Rust ● Static typed ●Compiled ahead of time ● Memory safety without Garbage Collector ● Abstractions without overhead
  • 3.
    Rust Project internally started byMozilla’s employee in the 2009 First pre-alpha release in January 2012 First stable release 1.0 on May 2015 Currently, July 2016, at version 1.9
  • 4.
    The aim ofthe language is to be as fast as C/C++ but safer and more expressive
  • 5.
    Why the name“Rust”
  • 6.
    Rust Graydon Hoare, the creatorof the language, named it after a fungus
  • 7.
  • 8.
    Hello World fn main(){ let x = 42; println!("Hello, world {}!", x); } Pure functions, and variables are not-mutable by default
  • 9.
    Enums enum Message { Quit, ChangeColor(i32,i32, i32), Move { x: i32, y: i32 }, Write(String), } Enumerators can have optional associated data
  • 10.
    Pattern Matching fn quit(){ /* ... */ } fn change_color(r: i32, g: i32, b: i32) { /* ... */ } fn move_cursor(x: i32, y: i32) { /* ... */ } fn process_message(msg: Message) { match msg { Message::Quit => quit(), Message::ChangeColor(r, g, b) => change_color(r, g, b), Message::Move { x: x, y: y } => move_cursor(x, y), Message::Write(s) => println!("{}", s), }; } Similar to switch case but more flexible on the matching
  • 11.
    Pattern Matching let x= '💅'; let y = 1; match x { 'a' ... 'j' => println!("early letter"), 'k' ... 'z' => println!("late letter"), _ => println!("something else"), } match y { 1 ... 5 => println!("one through five"), _ => println!("anything"), } ...Like those examples
  • 12.
    Structs struct Point { x:i32, y: i32, } fn main() { let origin = Point { x: 0, y: 0 }; // origin: Point println!("The origin is at ({}, {})", origin.x, origin.y); } Can have methods or Traits
  • 13.
    Methods struct Circle { x:f64, y: f64, radius: f64, } impl Circle { fn area(&self) -> f64 { std::f64::consts::PI * (self.radius * self.radius) } } fn main() { let c = Circle { x: 0.0, y: 0.0, radius: 2.0 }; println!("{}", c.area()); } Methods are just functions attached to a struct
  • 14.
    Traits struct Circle { x:f64, y: f64, radius: f64, } trait HasArea { fn area(&self) -> f64; } impl HasArea for Circle { fn area(&self) -> f64 { std::f64::consts::PI * (self.radius * self.radius) } } Traits are like interfaces; combine traits for polymorphism
  • 15.
    Iterators (1..) .filter(|&x| x %2 == 0) .filter(|&x| x % 3 == 0) .take(5) .collect::<Vec<i32>>(); Iterators help to build solutions with functional programming Functional programming is integrated within the language
  • 16.
  • 17.
    Ownership / 1 letv = 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]); You cannot use a value owned by someone else The compiler will throw an error for you
  • 18.
    Ownership / 2 fntake(v: Vec<i32>) { // what happens here isn’t important. } let v = vec![1, 2, 3]; take(v); println!("v[0] is: {}", v[0]); error: use of moved value: `v` println!("v[0] is: {}", v[0]); ^ Passing by value move the ownership as well
  • 19.
    Borrowing / 1 fnfoo(v: &Vec<i32>) -> i32 { // do stuff with v } let v = vec![1, 2, 3]; foo(&v); println!("v[0] is: {}", v[0]); // it works Avoid moving ownership by passing by reference References are immutable
  • 20.
    Borrowing / 2 fnbar(v: &mut Vec<i32>) { v.push(4) } let mut v = vec![1, 2, 3]; bar(v); println!("{:?}", v[0]); // [1, 2, 3, 4] Mutable references allows you to mutate the borrowed one
  • 21.
    Lifetimes / 1 structChild {} struct Parent { child: &Child } let child = Child{}; let parent = Parent{child: &child}; error: missing lifetime specifier [E0106] child: &Child ^~~~~~ Problem, when child goes out of scope parent will point to freed memory
  • 22.
    Lifetimes / 2 structChild {} struct Parent<'a> { child: &'a Child } let child = Child{}; let parent = Parent{child: &child}; We declare a lifetime ‘a, the compiler will free the memory of child when Parent’s memory is freed
  • 23.
  • 24.
    Compilation Language is translatedinto MIR and then compiled with LLVM Rust MIR LLVM ASM
  • 25.
    ● Desugaring ● ReduceRust to a simple core ● Create a control flow graph ● Simplify match expression, apply explicit drops and panics ● Output LLVM IR Optimisations MIR: mid-level IR
  • 26.
    MIR / 1 SimpleRust code... for elem in vec { process(elem); }
  • 27.
    MIR / 2 ...convertedinto partial MIR let mut iterator = IntoIterator::into_iter(vec); loop: match Iterator::next(&mut iterator) { Some(elem) => { process(elem); goto loop; } None => { goto break; } } break: ...
  • 28.
    LLVM ● Applies 100+between transformations and optimisations ● Link-time optimisations ● Target multiple platforms: x86, ARM, WebAssembly
  • 29.
    Final binary ● Thefinal binary is statically compiled ● No need of pre-installed runtime ● Only system provided libraries are linked
  • 30.
    Final binary https://github.com/brson/httptest compiledon macOS 10.15 with cargo build --release $ otool -L target/release/httptest target/release/httptest: /usr/lib/libssl.0.9.8.dylib /usr/lib/libcrypto.0.9.8.dylib /usr/lib/libSystem.B.dylib
  • 31.
    References ● Internet archaeology:the definitive, end-all source for why Rust is named "Rust" (https://www.reddit.com/r/rust/comments/27jvdt/internet_archae ology_the_definitive_endall_source/) ● Introducing MIR (http://blog.rust-lang.org/2016/04/19/MIR.html) ● Introduce a "mid-level IR" (MIR) into the compiler (https://github.com/nikomatsakis/rfcs/blob/mir/text/0000-mir.md)
  • 32.