Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hello, Rust! — An overview

Hello, Rust! — An overview

This talk is an overview of the Rust language. It has been presented during http://www.agendadulibre.org/events/12769. Not all slides have been detailed. The goal of this meetup was to have an overview of the Rust language, and to talk about what the public was curious about.

A live-coding/live-contribution session has also been organized at the end: Take a real project from the audience, see how to enhance it, how to be more idiomatic, better memory management, better data design etc.

C9eaecd38c8fa34ce638520112017f9a?s=128

Ivan Enderlin

February 02, 2017
Tweet

More Decks by Ivan Enderlin

Other Decks in Programming

Transcript

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

  2. Disclaimer • I am not an expert • “Rust is

    good at x” ⇏ “other languages are n00bs” • Not exhaustive, this is an overview!
  3. –me “A language is a way to express a solution

    to a problem”
  4. Agenda • Language • Ecosystem • Community • Interesting projects

  5. Language

  6. History • Father Graydon Hoare (thanks!) • Officially born in

    2009, announced in 2010 • 1.0 release the 15th of May 2015 • Sponsored by Mozilla Research
  7. tl;dr • Rust is a general-purpose, multi-paradigm, compiled programming language

    • Safe, concurrent, and practical • Ciao .
  8. 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
  9. Foundations • Mutability • Ownership • Borrowing • Lifetimes •

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

    Algebraic types Checked at compile time
  11. Mutability • Everything is immutable by default • mut to

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

    make a data mutable let x = 7; x = 42;
  13. 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;
  14. Mutability • Everything is immutable by default • mut to

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

    make a data mutable let mut x = 7; x = 42; println!("x = {}", x); x = 42
  16. 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
  17. Ownership The move semantics fn main() { let book =

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

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

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

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

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

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

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

    Book { /* … */ }; read_book(book); read_book(book); } fn read_book(book: Book) { // … }
  25. 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`
  26. –you “How to retrieve the book after read_book?”

  27. 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!
  28. 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
  29. fn main() { let book = Book { /* …

    */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference fn read_book(book: &Book) { // … }
  30. 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) { // … }
  31. 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) { // … }
  32. 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) { // … }
  33. 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) { // … }
  34. 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) { // … }
  35. 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) { // … }
  36. 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) { // … }
  37. 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) { // … }
  38. 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) { // … }
  39. 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) { // … }
  40. 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) { // … }
  41. fn main() { let book = Book { /* …

    */ }; read_book(&book); read_book(&book); } Borrowing &T is a reference fn read_book(book: &Book) { // … }
  42. –you “What if read_book mutates the book?”

  43. 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); }
  44. 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); }
  45. 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); }
  46. 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); }
  47. 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
  48. The rules Type Mutable Number of sharings T ❌ Zero

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

    &T ❌ One or more &mut T ✅ Exactly one i.e. many readers, one writer
  50. 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 .
  51. 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`
  52. 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
  53. Lifetime elision • Function body: Lifetime is always inferred •

    Function I/O: Lifetime can be ambiguous, so annotation might be required
  54. 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); }
  55. 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
  56. 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
  57. Lifetimes fn f<'a, 'b>(x: &'a str, y: &'b str) ->

    &'a str { y } error[E0312]: lifetime of reference outlives lifetime of borrowed content... --> <anon>:2:5 | 2 | y | ^ | note: ...the reference is valid for the lifetime 'a as defined on the block at 1:48... --> <anon>: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 --> <anon>: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 --> <anon>:1:1 | 1 | fn f<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { | ^
  58. Algebraic types • Types are inferred • What algebra means?

    • ربجلا = reunion (of broken parts) ✓ Reunion of types • Elementary algebra includes arithmetic operations, like ⨉ and +
  59. 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
  60. 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
  61. Units • Unit type is a degenerated form of a

    product type • Product of no type: No name and no operands () • Construct let unit = ();
  62. 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;
  63. 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;
  64. 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;
  65. Unit-like structures • Product type with a name and no

    operands struct Point { } struct Point • Construct let point = Point { }; let point = Point;
  66. 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) }
  67. Enumerators • Construct let message = Message::Move { x: 7,

    y: 42, z: 153 }; • Read let Message::Move { x, y, z } = message;
  68. ––Uncle Ben “With great power comes great responsibility”

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

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

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

    ––French National Convention (May 8th, 1793)
  72. 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
  73. Pattern matching Single patterns let x = 3; let number

    = match x { 1 => "one", 2 => "two", 3 => "three", 4 => "four", 5 => "five", _ => "something else" };
  74. 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") }
  75. 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") }
  76. Pattern matching Bindings let x = 5; match x {

    e @ 1 ... 3 | e @ 5 ... 7 => println!("got {}", e), _ => println!("anything"), }
  77. 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…") }
  78. 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…") }
  79. 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!
  80. 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"));
  81. 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”
  82. 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 };
  83. 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)
  84. 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…") }
  85. 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.") }
  86. Methods • Methods are functions bounded to a type •

    Structures • Enumerators • Primitives
  87. 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()); }
  88. 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()); }
  89. 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()); }
  90. 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()); }
  91. 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()); }
  92. 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()); }
  93. 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()); }
  94. 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?
  95. 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()); }
  96. 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()); }
  97. 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()); }
  98. Parametric polymorphism • Also known as Generic • Many (poly)

    forms (morph) • Static dispatch by default (monomorphization) • Dynamic dispatch for trait objects (not detailed, see doc)
  99. Parametric polymorphism Generic functions fn takes_anything<T>(x: T) { // …

    } takes_anything(7u8); takes_anything(4.2f32);
  100. Parametric polymorphism Generic functions fn takes_anything<T>(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);
  101. Parametric polymorphism Generic functions fn takes_anything<T>(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
  102. Parametric polymorphism Generic structures struct Point<T> { x: T, y:

    T } let int_origin = Point { x: 0, y: 0 }; let float_origin = Point { x: 0.0, y: 0.0 };
  103. Parametric polymorphism Generic enumerators enum Foo<T> { Bar, Baz(T), Qux

    { z: T } } let int_baz = Foo::Baz(0); let float_baz = Foo::Baz(0.0);
  104. Option • null does not exist in Rust • Option

    to represent an optional value enum Option<T> { Some(T), None } let x = Some(7); let y = None;
  105. Result • No exception in Rust • Result is the

    error handling mechanism enum Result<T, E> { Ok(T), Err(E) } let x = Ok(7); let y = Err("Too bad");
  106. 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
  107. Traits struct Circle { x : f64, y : f64,

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

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

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

    radius: f64 } trait HasArea { fn area(&self) -> f64; } impl HasArea for Circle { fn area(&self) -> f64 { … } }
  111. Traits Bound on generic functions fn print_area<T: HasArea>(shape: T) {

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

    println!("This shape has an area of {}", shape.area()); } T: HasArea means type T implements the HasArea trait
  113. Traits Bound on generic functions fn print_area<T: HasArea>(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
  114. Traits Multiple bounds on generic functions fn print_area<T: HasName +

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

    HasArea>(shape: T) { println!("{} has an area of {}", shape.name(), shape.area()); } + represents a list of traits
  116. Traits where clause fn print_area<T>(shape: T) where T: HasName +

    HasArea { println!("{} has an area of {}", shape.name(), shape.area()); }
  117. Traits where clause fn print_area<T>(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
  118. Traits Default methods trait Foo { fn is_valid(&self) -> bool;

    fn is_invalid(&self) -> bool { !self.is_valid() } } Can be overridden
  119. Traits Inheritance trait Foo { fn foo(&self); } trait FooBar

    : Foo { fn foobar(&self); }
  120. 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…)
  121. 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 }; }
  122. 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!
  123. 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!
  124. 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
  125. 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
  126. Slices • A dynamically-sized view into a contiguous sequence [T]

    • A slice is a subset of a collection struct Slice<T> { data : *const T, length: usize } • Work on subsets with no fear and no copy • All Rust guarantees apply!
  127. Macros • Hygienic system • Procedural macros • Long story

    short: It's cool and easy to use
  128. 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
  129. Iterators • Rust as its best • High-level constructions •

    Short and efficient low-level results • Strong safety guarantees • Producers and consumers model
  130. 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
  131. 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); }
  132. 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
  133. 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
  134. 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);
  135. 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
  136. 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)
  137. 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)
  138. 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
  139. 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
  140. 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
  141. 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
  142. Thread Basic usage use std::thread; fn main() { thread::spawn(|| {

    println!("Hello from a thread!"); }); }
  143. Thread Return a value use std::thread; fn main() { let

    handle = thread::spawn(|| { "Hello from a thread!" }); println!("{}", handle.join().unwrap()); }
  144. Thread Closure, references & move semantics fn main() { let

    x = 1; thread::spawn(|| { println!("x is {}", x); }); }
  145. 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); });
  146. 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); }); }
  147. –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.”
  148. 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…
  149. 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
  150. –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”
  151. 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
  152. Tests Unit and integration suites #[test] fn case_foo() { let

    input = …; let output = …; assert_eq!(sut(input), output); } $ cargo run --lib
  153. 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 { … }
  154. 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 { … }
  155. 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
  156. Ecosystem

  157. 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)
  158. rustc source HIR MIR LLVM IR target

  159. 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)
  160. rustup • Toolchain installer curl https://sh.rustup.rs -sSf | sh •

    Update rustup update • Easy cross-compilation rustup target add arm-linux-androideabi
  161. cargo • build • clean • doc • new •

    init • run • test • bench • install • … • Official package manager • Repository on crates.io • Invoke rustc for you
  162. 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
  163. 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/
  164. Play Rust https://play.rust-lang.org/

  165. Community

  166. 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
  167. 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
  168. Interesting projects

  169. Servo • https://servo.org/ • The Parallel Browser Engine Project •

    Stylo • Constellation • WebRender • … • Being integrated in Firefox (project Quantum)
  170. Redox • https://redox-os.org/ • Unix-like Operating System written in Rust

    • kernel • orbital • tfs • ralloc • ion
  171. 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 • …
  172. Mio & Tokio • https://tokio.rs/ • Metal I/O • A

    platform for writing fast networking code with Rust • Futures • Core • Proto(col) • Service
  173. 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() }
  174. 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
  175. • http://www.piston.rs/ • A modular open source game engine •

    Image • Music • Conrod, 2D GUI library • Gfx • Sprite • …
  176. ripgrep • https://github.com/BurntSushi/ ripgrep • Usability of The Silver Searcher

    with the raw speed of grep • Very fast
  177. Ruma • https://www.ruma.io/ • A Matrix homeserver written in Rust

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

    server
  179. editor • https://github.com/google/xi-editor • A modern editor with a backend

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

  181. 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 • …
  182. 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!
  183. Tagua VM • http://tagua.io/ • An experimental PHP Virtual Machine

    • Several libraries • Parser • Passes/analysis • Idiomatic LLVM bindings • Virtual Machine • All extensions • …
  184. Sorry if your awesome project is not here. And thanks

    for working on it ❤!
  185. 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/
  186. 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
  187. Q&A Thank you ❤ Ask me anything https://www.rust-lang.org/
 ivan.enderlin@hoa-project.net @mnt_io

    https://www.liip.ch/ https://hoa-project.net http://atoum.org http://tagua.io