briefly rust
TRANSCRIPT
Briefly RustDaniele 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 languageis 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 Matchinglet 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 programmingFunctional 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 elseThe 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 referenceReferences 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
OptimisationsMIR: mid-level IR
MIR / 1Simple 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/httptesttarget/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_archaeology_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/