Slide 1

Slide 1 text

Hello, Rust! An overview PhD. Ivan Enderlin February 2nd 2017

Slide 2

Slide 2 text

Disclaimer • I am not an expert • “Rust is good at x” ⇏ “other languages are n00bs” • Not exhaustive, this is an overview!

Slide 3

Slide 3 text

–me “A language is a way to express a solution to a problem”

Slide 4

Slide 4 text

Agenda • Language • Ecosystem • Community • Interesting projects

Slide 5

Slide 5 text

Language

Slide 6

Slide 6 text

History • Father Graydon Hoare (thanks!) • Officially born in 2009, announced in 2010 • 1.0 release the 15th of May 2015 • Sponsored by Mozilla Research

Slide 7

Slide 7 text

tl;dr • Rust is a general-purpose, multi-paradigm, compiled programming language • Safe, concurrent, and practical • Ciao .

Slide 8

Slide 8 text

Why Rust? • Low-level with no fear • Safety guarantees • Type system (algebraic types, associated types, kinds, inference, affine…) • Traits • Concurrency • Extremely fast • FFI • No garbage collector • Error handling • Community & documentation • Cross platform

Slide 9

Slide 9 text

Foundations • Mutability • Ownership • Borrowing • Lifetimes • Algebraic types

Slide 10

Slide 10 text

Foundations • Mutability • Ownership • Borrowing • Lifetimes • Algebraic types Checked at compile time

Slide 11

Slide 11 text

Mutability • Everything is immutable by default • mut to make a data mutable

Slide 12

Slide 12 text

Mutability • Everything is immutable by default • mut to make a data mutable let x = 7; x = 42;

Slide 13

Slide 13 text

Mutability • Everything is immutable by default • mut to make a data mutable error[E0384]: re-assignment of immutable variable `x` let x = 7; x = 42;

Slide 14

Slide 14 text

Mutability • Everything is immutable by default • mut to make a data mutable let mut x = 7; x = 42; println!("x = {}", x);

Slide 15

Slide 15 text

Mutability • Everything is immutable by default • mut to make a data mutable let mut x = 7; x = 42; println!("x = {}", x); x = 42

Slide 16

Slide 16 text

Ownership • Variable bindings (let) have a property in Rust: they “have ownership” of what they are bound to • When a binding goes out of scope, Rust will free the bound resources • This happens deterministically, at the end of the scope

Slide 17

Slide 17 text

Ownership The move semantics fn main() { let book = Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … }

Slide 18

Slide 18 text

Ownership The move semantics fn main() { let book = Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … } Rust The ultimate book

Slide 19

Slide 19 text

Ownership The move semantics fn main() { let book = Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … } Rust The ultimate book

Slide 20

Slide 20 text

Ownership The move semantics fn main() { let book = Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … } Rust The ultimate book

Slide 21

Slide 21 text

Ownership The move semantics fn main() { let book = Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … } Rust The ultimate book

Slide 22

Slide 22 text

Ownership The move semantics fn main() { let book = Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … } Rust The ultimate book

Slide 23

Slide 23 text

Ownership The move semantics fn main() { let book = Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … }

Slide 24

Slide 24 text

Ownership The move semantics fn main() { let book = Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … }

Slide 25

Slide 25 text

Ownership The move semantics fn main() { let book = Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … } error[E0382]: use of moved value: `book`

Slide 26

Slide 26 text

–you “How to retrieve the book after read_book?”

Slide 27

Slide 27 text

Ownership Retrieve the book fn read_book(book: Book) -> Book { // … book } Solution 1 Return the data Solution 2 Clone book before passing it to read_book Solution 3 Share it!

Slide 28

Slide 28 text

Borrowing • We call the &T type a “reference” • Rather than owning the resource, a binding borrows ownership • A binding that borrows something does not deallocate the resource when it goes out of scope • A borrowed resource is immutable

Slide 29

Slide 29 text

fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference fn read_book(book: &Book) { // … }

Slide 30

Slide 30 text

Rust The ultimate book Rust The ultimate book fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 31

Slide 31 text

Rust The ultimate book Rust The ultimate book fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 32

Slide 32 text

Rust The ultimate book Rust The ultimate book fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 33

Slide 33 text

Rust The ultimate book Rust The ultimate book fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 34

Slide 34 text

Rust The ultimate book Rust The ultimate book fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 35

Slide 35 text

Rust The ultimate book fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 36

Slide 36 text

Rust The ultimate book fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 37

Slide 37 text

Rust The ultimate book fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 38

Slide 38 text

Rust The ultimate book fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 39

Slide 39 text

fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 40

Slide 40 text

fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference Rust The ultimate book fn read_book(book: &Book) { // … }

Slide 41

Slide 41 text

fn main() { let book = Book { /* … */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference fn read_book(book: &Book) { // … }

Slide 42

Slide 42 text

–you “What if read_book mutates the book?”

Slide 43

Slide 43 text

Borrowing &mut T is a mutable reference fn read_book(book: &mut Book) { book.name = String::from("bar"); } fn main() { let mut book = Book { name: String::from("foo") }; read_book(&mut book); println!("Book name is {}", book.name); }

Slide 44

Slide 44 text

Borrowing &mut T is a mutable reference fn read_book(book: &mut Book) { book.name = String::from("bar"); } fn main() { let mut book = Book { name: String::from("foo") }; read_book(&mut book); println!("Book name is {}", book.name); }

Slide 45

Slide 45 text

Borrowing &mut T is a mutable reference fn read_book(book: &mut Book) { book.name = String::from("bar"); } fn main() { let mut book = Book { name: String::from("foo") }; read_book(&mut book); println!("Book name is {}", book.name); }

Slide 46

Slide 46 text

Borrowing &mut T is a mutable reference fn read_book(book: &mut Book) { book.name = String::from("bar"); } fn main() { let mut book = Book { name: String::from("foo") }; read_book(&mut book); println!("Book name is {}", book.name); }

Slide 47

Slide 47 text

Borrowing &mut T is a mutable reference fn read_book(book: &mut Book) { book.name = String::from("bar"); } fn main() { let mut book = Book { name: String::from("foo") }; read_book(&mut book); println!("Book name is {}", book.name); } Book name is bar

Slide 48

Slide 48 text

The rules Type Mutable Number of sharings T ❌ Zero &T ❌ One or more &mut T ✅ Exactly one

Slide 49

Slide 49 text

The rules Type Mutable Number of sharings T ❌ Zero &T ❌ One or more &mut T ✅ Exactly one i.e. many readers, one writer

Slide 50

Slide 50 text

Lifetimes • Each reference has a lifetime • Prevent dangling pointer, aka use after free • Let the following scenario: • I have a data, • I send you a reference to this data, • I am done with it, and I deallocate it, while you still have the reference, • You use this data, and .

Slide 51

Slide 51 text

Lifetimes let x; // Introduce `x` { let y = 7; // Introduce scoped value `y` x = &y; // Store reference of `y` in `x` } // `y` goes out of scope and is dropped println!("{}", x); // `x` still refers to `y`

Slide 52

Slide 52 text

Lifetimes let x; // Introduce `x` { let y = 7; // Introduce scoped value `y` x = &y; // Store reference of `y` in `x` } // `y` goes out of scope and is dropped println!("{}", x); // `x` still refers to `y` error: `y` does not live long enough | 4 | x = &y; | - borrow occurs here 5 | } | ^ `y` dropped here while still borrowed ... 8 | } | - borrowed value needs to live until here

Slide 53

Slide 53 text

Lifetime elision • Function body: Lifetime is always inferred • Function I/O: Lifetime can be ambiguous, so annotation might be required

Slide 54

Slide 54 text

Lifetimes fn f(x: &str, y: &str) -> &str { x } fn main() { let x = "foo"; let z; { let y = "bar"; z = f(x, y); } println!("z = {}", z); }

Slide 55

Slide 55 text

Lifetimes fn f(x: &str, y: &str) -> &str { x } fn main() { let x = "foo"; let z; { let y = "bar"; z = f(x, y); } println!("z = {}", z); } ^ expected lifetime parameter error[E0106]: missing lifetime specifier

Slide 56

Slide 56 text

Lifetimes fn f<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { x } fn main() { let x = "foo"; let z; { let y = "bar"; z = f(x, y); } println!("z = {}", z); } • 'a means lifetime a • &'a means the reference has lifetime a • f<'a, 'b> means f has 2 explicit lifetimes

Slide 57

Slide 57 text

Lifetimes fn f<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { y } error[E0312]: lifetime of reference outlives lifetime of borrowed content... --> :2:5 | 2 | y | ^ | note: ...the reference is valid for the lifetime 'a as defined on the block at 1:48... --> :1:49 | 1 | fn f<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { | ^ note: ...but the borrowed content is only valid for the lifetime 'b as defined on the block at 1:48 --> :1:49 | 1 | fn f<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { | ^ help: consider using an explicit lifetime parameter as shown: fn f<'a>(x: &'a str, y: &'a str) -> &'a str --> :1:1 | 1 | fn f<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { | ^

Slide 58

Slide 58 text

Algebraic types • Types are inferred • What algebra means? • ربجلا = reunion (of broken parts) ✓ Reunion of types • Elementary algebra includes arithmetic operations, like ⨉ and +

Slide 59

Slide 59 text

Product types • S = T1 ⨉ T2 ⨉ … ⨉ Ti ⨉ … ⨉ Tm where Ti is a type ‣ S = T1 ⋀ T2 ⋀ … ⋀ Ti ⋀ … ⋀ Tm • S is called a product type • Ti is called an operand of S • Size of a value v: S is the sum of the size of all Ti

Slide 60

Slide 60 text

Sum types • E = T1 + T2 + … + Ti + … + Tm where Ti is a type ‣ E = T1 ⋁ T2 ⋁ … ⋁ Ti ⋁ … ⋁ Tm • E is called a sum type, or a tagged union • Ti is called a variant of E • A value v: E has one type Ti represented by a tag

Slide 61

Slide 61 text

Units • Unit type is a degenerated form of a product type • Product of no type: No name and no operands () • Construct let unit = ();

Slide 62

Slide 62 text

Tuples • Product type with no name and indexed operands (i32, i32, i32) • Construct let point = (7, 42, 153); • Read let x = point.0; let (x, _, z) = point;

Slide 63

Slide 63 text

Tuple structures • Product type with a name and indexed operands struct Point(i32, i32, i32) • Construct let point = Point(7, 42, 153); • Read let Point(x, y, z) = point;

Slide 64

Slide 64 text

Structures • Product type with a name and named operands struct Point { x: i32, y: i32, z: i32 } • Construct let point = Point { x: 7, y: 42, z: 153 }; • Read let x = point.x; let Point { x, .. } = point;

Slide 65

Slide 65 text

Unit-like structures • Product type with a name and no operands struct Point { } struct Point • Construct let point = Point { }; let point = Point;

Slide 66

Slide 66 text

Enumerators • Sum type with one or more variants • Each variant can be of any type (tuple, structure…) enum Message { Quit, ChangeColor(i32, i32, i32, i32), Move { x: i32, y: i32, z: i32 }, Private(String), Public(String) }

Slide 67

Slide 67 text

Enumerators • Construct let message = Message::Move { x: 7, y: 42, z: 153 }; • Read let Message::Move { x, y, z } = message;

Slide 68

Slide 68 text

––Uncle Ben “With great power comes great responsibility”

Slide 69

Slide 69 text

––Uncle Ben “With great power comes great responsibility” ––Winston Churchill

Slide 70

Slide 70 text

––Uncle Ben “With great power comes great responsibility” ––Winston Churchill ––French National Convention (May 8th, 1793)

Slide 71

Slide 71 text

––Uncle Ben “With great power comes great responsibility” ––Winston Churchill ––French National Convention (May 8th, 1793)

Slide 72

Slide 72 text

Pattern matching • match is like if/else with super powers • Can benefit from all types • If not exhaustive, compiler will yell • e.g. a variant of an enumerator is missing • i.e. not tested

Slide 73

Slide 73 text

Pattern matching Single patterns let x = 3; let number = match x { 1 => "one", 2 => "two", 3 => "three", 4 => "four", 5 => "five", _ => "something else" };

Slide 74

Slide 74 text

Pattern matching Multiple patterns let x = 3; match x { 1 | 2 | 3 => println!("one or two or three"), 4 => println!("four"), 5 | 6 | 7 => println!("five or six or seven"), _ => println!("anything") }

Slide 75

Slide 75 text

Pattern matching Ranges let x = 7; match x { 1 ... 3 => println!("one or two or three"), 4 => println!("four"), 5 ... 7 => println!("five or six or seven"), _ => println!("anything") }

Slide 76

Slide 76 text

Pattern matching Bindings let x = 5; match x { e @ 1 ... 3 | e @ 5 ... 7 => println!("got {}", e), _ => println!("anything"), }

Slide 77

Slide 77 text

Pattern matching Destructuring match message { Message::Quit => println!("Bye bye!"), Message::Public(message) => println!("“{}”", message), Message::Move { x, y, .. } => println!("Move to ({}, {})", x, y), _ => println!("Oops…") }

Slide 78

Slide 78 text

Pattern matching Destructuring let message = Message::Quit; match message { Message::Quit => println!("Bye bye!"), Message::Public(message) => println!("“{}”", message), Message::Move { x, y, .. } => println!("Move to ({}, {})", x, y), _ => println!("Oops…") }

Slide 79

Slide 79 text

Pattern matching Destructuring let message = Message::Quit; match message { Message::Quit => println!("Bye bye!"), Message::Public(message) => println!("“{}”", message), Message::Move { x, y, .. } => println!("Move to ({}, {})", x, y), _ => println!("Oops…") } Bye bye!

Slide 80

Slide 80 text

Pattern matching Destructuring match message { Message::Quit => println!("Bye bye!"), Message::Public(message) => println!("“{}”", message), Message::Move { x, y, .. } => println!("Move to ({}, {})", x, y), _ => println!("Oops…") } let message = Message::Public(String::from("hello"));

Slide 81

Slide 81 text

Pattern matching Destructuring match message { Message::Quit => println!("Bye bye!"), Message::Public(message) => println!("“{}”", message), Message::Move { x, y, .. } => println!("Move to ({}, {})", x, y), _ => println!("Oops…") } let message = Message::Public(String::from("hello")); “hello”

Slide 82

Slide 82 text

Pattern matching Destructuring match message { Message::Quit => println!("Bye bye!"), Message::Public(message) => println!("“{}”", message), Message::Move { x, y, .. } => println!("Move to ({}, {})", x, y), _ => println!("Oops…") } let message = Message::Move { x: 7, y: 42, z: 153 };

Slide 83

Slide 83 text

Pattern matching Destructuring match message { Message::Quit => println!("Bye bye!"), Message::Public(message) => println!("“{}”", message), Message::Move { x, y, .. } => println!("Move to ({}, {})", x, y), _ => println!("Oops…") } let message = Message::Move { x: 7, y: 42, z: 153 }; Move to (7, 42)

Slide 84

Slide 84 text

Pattern matching Destructuring match message { Message::Quit => println!("Bye bye!"), Message::Public(message) => println!("“{}”", message), Message::Move { x, y, .. } => println!("Move to ({}, {})", x, y), _ => println!("Oops…") }

Slide 85

Slide 85 text

Pattern matching Guards enum OptionalInt { Value(i32), MissingValue, } let x = OptionalInt::Value(5); match x { OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than 5!"), OptionalInt::Value(..) => println!("Got an int!"), OptionalInt::Missing => println!("No such luck.") }

Slide 86

Slide 86 text

Methods • Methods are functions bounded to a type • Structures • Enumerators • Primitives

Slide 87

Slide 87 text

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()); }

Slide 88

Slide 88 text

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()); }

Slide 89

Slide 89 text

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()); }

Slide 90

Slide 90 text

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()); }

Slide 91

Slide 91 text

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()); }

Slide 92

Slide 92 text

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()); }

Slide 93

Slide 93 text

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()); }

Slide 94

Slide 94 text

Methods • First parameter is special: self • self if it's a value on the stack, take ownership • &self if it's a reference • &mut self if it's a mutable reference • What if no self provided?

Slide 95

Slide 95 text

Associated functions impl Circle { fn new(x: f64, y: f64, radius: f64) -> Circle { Circle { x : x, y : y, radius: radius } } fn area(&self) -> f64 { … } } fn main() { let c = Circle::new(0.0, 0.0, 2.0); println!("{}", c.area()); }

Slide 96

Slide 96 text

Associated functions impl Circle { fn new(x: f64, y: f64, radius: f64) -> Circle { Circle { x : x, y : y, radius: radius } } fn area(&self) -> f64 { … } } fn main() { let c = Circle::new(0.0, 0.0, 2.0); println!("{}", c.area()); }

Slide 97

Slide 97 text

Associated functions impl Circle { fn new(x: f64, y: f64, radius: f64) -> Circle { Circle { x : x, y : y, radius: radius } } fn area(&self) -> f64 { … } } fn main() { let c = Circle::new(0.0, 0.0, 2.0); println!("{}", c.area()); }

Slide 98

Slide 98 text

Parametric polymorphism • Also known as Generic • Many (poly) forms (morph) • Static dispatch by default (monomorphization) • Dynamic dispatch for trait objects (not detailed, see doc)

Slide 99

Slide 99 text

Parametric polymorphism Generic functions fn takes_anything(x: T) { // … } takes_anything(7u8); takes_anything(4.2f32);

Slide 100

Slide 100 text

Parametric polymorphism Generic functions fn takes_anything(x: T) { // … } takes_anything(7u8); takes_anything(4.2f32); fn takes_anything_u8(x: u8) { // … } fn takes_anything_f32(x: f32) { // … } takes_anything_u8(7u8); takes_anything_f32(4.2f32);

Slide 101

Slide 101 text

Parametric polymorphism Generic functions fn takes_anything(x: T) { // … } takes_anything(7u8); takes_anything(4.2f32); fn takes_anything_u8(x: u8) { // … } fn takes_anything_f32(x: f32) { // … } takes_anything_u8(7u8); takes_anything_f32(4.2f32); Statically dispatched by the compiler

Slide 102

Slide 102 text

Parametric polymorphism Generic structures struct Point { x: T, y: T } let int_origin = Point { x: 0, y: 0 }; let float_origin = Point { x: 0.0, y: 0.0 };

Slide 103

Slide 103 text

Parametric polymorphism Generic enumerators enum Foo { Bar, Baz(T), Qux { z: T } } let int_baz = Foo::Baz(0); let float_baz = Foo::Baz(0.0);

Slide 104

Slide 104 text

Option • null does not exist in Rust • Option to represent an optional value enum Option { Some(T), None } let x = Some(7); let y = None;

Slide 105

Slide 105 text

Result • No exception in Rust • Result is the error handling mechanism enum Result { Ok(T), Err(E) } let x = Ok(7); let y = Err("Too bad");

Slide 106

Slide 106 text

Traits • Object, interface, type capability… all mixed • Tells the compiler about functionality a type must provide • Can be implemented on any types (structures, enumerators, primitive types) • This is where things becomes very interesting and delicious

Slide 107

Slide 107 text

Traits struct Circle { x : f64, y : f64, radius: f64 } trait HasArea { fn area(&self) -> f64; } impl HasArea for Circle { fn area(&self) -> f64 { … } }

Slide 108

Slide 108 text

Traits struct Circle { x : f64, y : f64, radius: f64 } trait HasArea { fn area(&self) -> f64; } impl HasArea for Circle { fn area(&self) -> f64 { … } }

Slide 109

Slide 109 text

Traits struct Circle { x : f64, y : f64, radius: f64 } trait HasArea { fn area(&self) -> f64; } impl HasArea for Circle { fn area(&self) -> f64 { … } }

Slide 110

Slide 110 text

Traits struct Circle { x : f64, y : f64, radius: f64 } trait HasArea { fn area(&self) -> f64; } impl HasArea for Circle { fn area(&self) -> f64 { … } }

Slide 111

Slide 111 text

Traits Bound on generic functions fn print_area(shape: T) { println!("This shape has an area of {}", shape.area()); }

Slide 112

Slide 112 text

Traits Bound on generic functions fn print_area(shape: T) { println!("This shape has an area of {}", shape.area()); } T: HasArea means type T implements the HasArea trait

Slide 113

Slide 113 text

Traits Bound on generic functions fn print_area(shape: T) { println!("This shape has an area of {}", shape.area()); } T: HasArea means type T implements the HasArea trait Monomorphization applies, i.e. statically dispatched

Slide 114

Slide 114 text

Traits Multiple bounds on generic functions fn print_area(shape: T) { println!("{} has an area of {}", shape.name(), shape.area()); }

Slide 115

Slide 115 text

Traits Multiple bounds on generic functions fn print_area(shape: T) { println!("{} has an area of {}", shape.name(), shape.area()); } + represents a list of traits

Slide 116

Slide 116 text

Traits where clause fn print_area(shape: T) where T: HasName + HasArea { println!("{} has an area of {}", shape.name(), shape.area()); }

Slide 117

Slide 117 text

Traits where clause fn print_area(shape: T) where T: HasName + HasArea { println!("{} has an area of {}", shape.name(), shape.area()); } where allows to express traits on type, just like before More powerful syntax, not detailed here

Slide 118

Slide 118 text

Traits Default methods trait Foo { fn is_valid(&self) -> bool; fn is_invalid(&self) -> bool { !self.is_valid() } } Can be overridden

Slide 119

Slide 119 text

Traits Inheritance trait Foo { fn foo(&self); } trait FooBar : Foo { fn foobar(&self); }

Slide 120

Slide 120 text

RAII • Resource Acquisition Is Initialisation • No manual allocation, no manual deallocation, no garbage collector • The Drop trait is used to run some code when a value goes out of scope • Default implementations for particular types (Rc, Weak, Arc…)

Slide 121

Slide 121 text

Drop struct Firework { strength: i32 } impl Drop for Firework { fn drop(&mut self) { println!("BOOM times {}!", self.strength); } } fn main() { let firecracker = Firework { strength: 1 }; let tnt = Firework { strength: 100 }; }

Slide 122

Slide 122 text

Drop struct Firework { strength: i32 } impl Drop for Firework { fn drop(&mut self) { println!("BOOM times {}!", self.strength); } } fn main() { let firecracker = Firework { strength: 1 }; let tnt = Firework { strength: 100 }; } BOOM times 100!

Slide 123

Slide 123 text

Drop struct Firework { strength: i32 } impl Drop for Firework { fn drop(&mut self) { println!("BOOM times {}!", self.strength); } } fn main() { let firecracker = Firework { strength: 1 }; let tnt = Firework { strength: 100 }; } BOOM times 1!

Slide 124

Slide 124 text

Drop struct Firework { strength: i32 } impl Drop for Firework { fn drop(&mut self) { println!("BOOM times {}!", self.strength); } } fn main() { let firecracker = Firework { strength: 1 }; let tnt = Firework { strength: 100 }; } BOOM times 1! First in, last out

Slide 125

Slide 125 text

Stack & Heap • Everything is allocated on the stack by default • Fast • Scoped to the function • Limited in size • To allocate on the heap, use Box

Slide 126

Slide 126 text

Slices • A dynamically-sized view into a contiguous sequence [T] • A slice is a subset of a collection struct Slice { data : *const T, length: usize } • Work on subsets with no fear and no copy • All Rust guarantees apply!

Slide 127

Slide 127 text

Macros • Hygienic system • Procedural macros • Long story short: It's cool and easy to use

Slide 128

Slide 128 text

Unsafety • Some programs are safe but cannot be verified by the compiler • unsafe keyword only allows three things: 1. Access or update a static mutable variable 2. Dereference a raw pointer 3. Call unsafe functions (the most powerful ability) • Does not turn off the borrow checker or other guarantees • See documentation for more details

Slide 129

Slide 129 text

Iterators • Rust as its best • High-level constructions • Short and efficient low-level results • Strong safety guarantees • Producers and consumers model

Slide 130

Slide 130 text

Iterators Basic example let a = [1, 2, 3]; let iterator = a.into_iter().map(|x| 2 * x); for i in iterator { println!("{}", i); } 2 4 6

Slide 131

Slide 131 text

Iterators Basic example, unfolded let a = [1, 2, 3]; let mut iterator = a.into_iter().map(|x| 2 * x); while let Some(i) = iterator.next() { println!("{}", i); }

Slide 132

Slide 132 text

Iterators Basic example, unfolded let a = [1, 2, 3]; let mut iterator = a.into_iter().map(|x| 2 * x); while let Some(i) = iterator.next() { println!("{}", i); } Producer

Slide 133

Slide 133 text

Iterators Basic example, unfolded let a = [1, 2, 3]; let mut iterator = a.into_iter().map(|x| 2 * x); while let Some(i) = iterator.next() { println!("{}", i); } Consumer

Slide 134

Slide 134 text

Iterators Producers & consumers explained let a = [1u32, 2, 3, 4, 6, 7, 8]; let sum: u32 = a.into_iter() .filter(|&x| x % 2 == 0) .map(|x| x * 2) .sum(); println!("sum is {}", sum);

Slide 135

Slide 135 text

Iterators Producers & consumers explained let a = [1u32, 2, 3, 4, 6, 7, 8]; let sum: u32 = a.into_iter() .filter(|&x| x % 2 == 0) .map(|x| x * 2) .sum(); println!("sum is {}", sum); Create an iterator

Slide 136

Slide 136 text

Iterators Producers & consumers explained let a = [1u32, 2, 3, 4, 6, 7, 8]; let sum: u32 = a.into_iter() .filter(|&x| x % 2 == 0) .map(|x| x * 2) .sum(); println!("sum is {}", sum); Producer: Filter results (note the &x)

Slide 137

Slide 137 text

Iterators Producers & consumers explained let a = [1u32, 2, 3, 4, 6, 7, 8]; let sum: u32 = a.into_iter() .filter(|&x| x % 2 == 0) .map(|x| x * 2) .sum(); println!("sum is {}", sum); Producer: Map results (note the x)

Slide 138

Slide 138 text

Iterators Producers & consumers explained let a = [1u32, 2, 3, 4, 6, 7, 8]; let sum: u32 = a.into_iter() .filter(|&x| x % 2 == 0) .map(|x| x * 2) .sum(); println!("sum is {}", sum); Consumer: Collect by summing results

Slide 139

Slide 139 text

Iterators Producers & consumers explained let a = [1u32, 2, 3, 4, 6, 7, 8]; let sum: u32 = a.into_iter() .filter(|&x| x % 2 == 0) .map(|x| x * 2) .sum(); println!("sum is {}", sum); sum is 40

Slide 140

Slide 140 text

Concurrency & parallelism • Hard & long, but incredibly important topics • Voluntarily small but powerful API in std • Two traits & the borrow checker to ensure safety • Several libraries to go further

Slide 141

Slide 141 text

Send & Sync • When a type T implements Send, it indicates that something of this type is able to have ownership transferred safely between threads • When a type T implements Sync, it indicates that something of this type has no possibility of introducing memory unsafety when used from multiple threads concurrently through shared references

Slide 142

Slide 142 text

Thread Basic usage use std::thread; fn main() { thread::spawn(|| { println!("Hello from a thread!"); }); }

Slide 143

Slide 143 text

Thread Return a value use std::thread; fn main() { let handle = thread::spawn(|| { "Hello from a thread!" }); println!("{}", handle.join().unwrap()); }

Slide 144

Slide 144 text

Thread Closure, references & move semantics fn main() { let x = 1; thread::spawn(|| { println!("x is {}", x); }); }

Slide 145

Slide 145 text

Thread Closure, references & move semantics fn main() { let x = 1; thread::spawn(|| { println!("x is {}", x); }); } 5:19: 7:6 error: closure may outlive the current function, but it borrows `x`, which is owned by the current function ... 5:19: 7:6 help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword, as shown: thread::spawn(move || { println!("x is {}", x); });

Slide 146

Slide 146 text

Thread Closure, references & move semantics 5:19: 7:6 error: closure may outlive the current function, but it borrows `x`, which is owned by the current function ... 5:19: 7:6 help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword, as shown: thread::spawn(move || { println!("x is {}", x); }); fn main() { let x = 1; thread::spawn(move || { println!("x is {}", x); }); }

Slide 147

Slide 147 text

–Someone “Shared mutable state is the root of all evil. Most languages attempt to deal with this problem through the ‘mutable’ part, but Rust deals with it by solving the ‘shared’ part.”

Slide 148

Slide 148 text

Thread Safe Shared Mutable State • Rc, a single-threaded reference-counting pointer, immutable, no Send or Sync • Cell or RefCell to get immutability • Arc, a thread-safe (atomic) reference-counting pointer, immutable, with Send and Sync • Mutex or RwLock (or more) to get mutability • more…

Slide 149

Slide 149 text

Thread Balance • Some constraints can be checked at compile-time with the borrow checker, traits etc. • Some constraints are checked at runtime • My advices 1. Check if a crate already exists 2. Check “big projects”, e.g. Servo or Redox

Slide 150

Slide 150 text

–Edsger W. Dijkstra, "The Humble Programmer" (1972) “Program testing can be a very effective way to show the presence of bugs, but it is hopelessly inadequate for showing their absence”

Slide 151

Slide 151 text

Tests • Rust hardly tries to ensure a high quality ecosystem • Simple but efficient mechanisms to write and run tests • cargo test to run them all

Slide 152

Slide 152 text

Tests Unit and integration suites #[test] fn case_foo() { let input = …; let output = …; assert_eq!(sut(input), output); } $ cargo run --lib

Slide 153

Slide 153 text

Tests Documentation /// Short description. /// /// Detailed description. /// /// # Examples /// /// ``` /// struct S { x: u32, y: u32 } /// # fn main() { /// let input = S { x: 7, y: 42 }; /// let output = …; /// /// assert_eq!(sut(input), output); /// ); /// # } /// ``` fn sut(s: S) -> t { … }

Slide 154

Slide 154 text

Tests Documentation /// Short description. /// /// Detailed description. /// /// # Examples /// /// ``` /// struct S { x: u32, y: u32 } /// # fn main() { /// let input = S { x: 7, y: 42 }; /// let output = …; /// /// assert_eq!(sut(input), output); /// ); /// # } /// ``` fn sut(s: S) -> t { … }

Slide 155

Slide 155 text

Tests Documentation /// Short description. /// /// Detailed description. /// /// # Examples /// /// ``` /// struct S { x: u32, y: u32 } /// # fn main() { /// let input = S { x: 7, y: 42 }; /// let output = …; /// /// assert_eq!(sut(input), output); /// ); /// # } /// ``` fn sut(s: S) -> t { … } • cargo test --doc • compile and run each examples as a standalone program • cargo doc • compile the documentation into HTML

Slide 156

Slide 156 text

Ecosystem

Slide 157

Slide 157 text

Compiler • Self-hosted compiler (Rust is written in Rust) • New release every 6 weeks • Different channels: stable, beta, nightly • LLVM for the backend • Lot of target triples supported • Including WebAssembly (experimental)

Slide 158

Slide 158 text

rustc source HIR MIR LLVM IR target

Slide 159

Slide 159 text

Crate • Can be a binary • Can be a library of type • lib (ambiguous) • dylib (.so, .dylib, .dll) • rlib (Rust static lib) • staticlib (.a, .lib) • cdylib (.so, .dylib, .dll) • proc-macro (procedural macros)

Slide 160

Slide 160 text

rustup • Toolchain installer curl https://sh.rustup.rs -sSf | sh • Update rustup update • Easy cross-compilation rustup target add arm-linux-androideabi

Slide 161

Slide 161 text

cargo • build • clean • doc • new • init • run • test • bench • install • … • Official package manager • Repository on crates.io • Invoke rustc for you

Slide 162

Slide 162 text

xargo • Sysroot manager to build and customise std • Cross compile Rust crates for targets that don't have binary releases of the standard crates cargo install xargo xargo build … • CLI is exactly like cargo

Slide 163

Slide 163 text

Documentations • Book, https://doc.rust-lang.org/book/ • FAQ, https://www.rust-lang.org/en-US/faq.html • rustc --explain • std, https://doc.rust-lang.org/std/ • Rust by example, http://rustbyexample.com/ • into_rust(), http://intorust.com/

Slide 164

Slide 164 text

Play Rust https://play.rust-lang.org/

Slide 165

Slide 165 text

Community

Slide 166

Slide 166 text

Gardens • Forum, https://users.rust-lang.org • Reddit, https://reddit.com/r/rust • IRC, irc://irc.mozilla.org#rust • YouTube, https://www.youtube.com/channel/UC… • Twitter, https://twitter.com/rustlang

Slide 167

Slide 167 text

Gardens • This week in Rust, https://this-week-in-rust.org/ • Blog, https://blog.rust-lang.org/ • Teams, https://www.rust-lang.org/en-US/team.html

Slide 168

Slide 168 text

Interesting projects

Slide 169

Slide 169 text

Servo • https://servo.org/ • The Parallel Browser Engine Project • Stylo • Constellation • WebRender • … • Being integrated in Firefox (project Quantum)

Slide 170

Slide 170 text

Redox • https://redox-os.org/ • Unix-like Operating System written in Rust • kernel • orbital • tfs • ralloc • ion

Slide 171

Slide 171 text

ralloc • https://github.com/redox-os/ralloc • A fast & memory efficient userspace allocator • Thread-local allocation • First-class debugger support • Logging • Custom out-of-memory handlers • Thread-specific OOM handlers • Partial deallocation • Platform agnostic • Safe SBRK • Useless alignments • Top notch security • …

Slide 172

Slide 172 text

Mio & Tokio • https://tokio.rs/ • Metal I/O • A platform for writing fast networking code with Rust • Futures • Core • Proto(col) • Service

Slide 173

Slide 173 text

Rayon • https://github.com/nikomatsakis/rayon/ • A data parallelism library for Rust • s/.iter()/.par_iter()/g, tadaa fn sum_of_squares(input: &[i32]) -> i32 { input.par_iter() .map(|&i| i * i) .sum() }

Slide 174

Slide 174 text

Web, ORM, HTTP • http://arewewebyet.org • http://ironframework.io/ • Extensible, concurrent web framework • http://diesel.rs/ • Safe, extensible ORM and query builder • https://hyper.rs/ • Low-level typesafe abstraction over raw HTTP • Provides an elegant layer over "stringly-typed" HTTP

Slide 175

Slide 175 text

• http://www.piston.rs/ • A modular open source game engine • Image • Music • Conrod, 2D GUI library • Gfx • Sprite • …

Slide 176

Slide 176 text

ripgrep • https://github.com/BurntSushi/ ripgrep • Usability of The Silver Searcher with the raw speed of grep • Very fast

Slide 177

Slide 177 text

Ruma • https://www.ruma.io/ • A Matrix homeserver written in Rust

Slide 178

Slide 178 text

trust-dns • https://github.com/bluejekyll/trust-dns • A Rust based DNS client and server

Slide 179

Slide 179 text

editor • https://github.com/google/xi-editor • A modern editor with a backend written in Rust

Slide 180

Slide 180 text

Alacritty • https://github.com/jwilm/alacritty • A cross-platform, GPU-accelerated terminal emulator

Slide 181

Slide 181 text

nom • https://github.com/Geal/nom/ • Rust parser combinator framework • Byte-, bit-, string-oriented • Zero-copy • Streaming • Macro based syntax • State machine handling • Descriptive errors • Custom error types • Safe parsing • Fast • …

Slide 182

Slide 182 text

Writing an OS in Rust • http://os.phil-opp.com/ • A series of articles explaining how to write an OS in Rust • Very interesting and instructive!

Slide 183

Slide 183 text

Tagua VM • http://tagua.io/ • An experimental PHP Virtual Machine • Several libraries • Parser • Passes/analysis • Idiomatic LLVM bindings • Virtual Machine • All extensions • …

Slide 184

Slide 184 text

Sorry if your awesome project is not here. And thanks for working on it ❤!

Slide 185

Slide 185 text

et cætera • It was just an overview • Tons of interesting ideas and projects • Nothing new in Rust, just 40 years of research finally in a single efficient & productive language • RustBelt, Formally verify several Rust safety properties, http://plv.mpi- sws.org/rustbelt/

Slide 186

Slide 186 text

Sources for this talk • Rust Book and various documentations • Blog posts • My experience and understanding • I have learned a lot, and I still have a lot to learn

Slide 187

Slide 187 text

Q&A Thank you ❤ Ask me anything https://www.rust-lang.org/
 [email protected] @mnt_io https://www.liip.ch/ https://hoa-project.net http://atoum.org http://tagua.io