CppNow 2017

CppNow 2017

Keynote from CppNow 2017

8f9e4181f2951ca8f21ed5c541686367?s=128

nikomatsakis

May 16, 2017
Tweet

Transcript

  1. 1 Hack without fear! Hack without fear!

  2. 2

  3. 3 What Rust has to offer Strong safety guarantees… No

    seg-faults, no data-races, expressive type system. …without compromising on performance. No garbage collector, no runtime. Goal: Confident, productive systems programming
  4. 4 Two years old on May 15! •••

  5. 5 Photo credit: FrontOffice https://commons.wikimedia.org/wiki/File:VIE_Office_Park.JPG

  6. 6 Photo credit: Artaxerxes https://commons.wikimedia.org/wiki/File:Grindstone_Cafe_in_Lyndonville_Vermont.jpg

  7. 7 Photo credit: Artaxerxes https://commons.wikimedia.org/wiki/File:Grindstone_Cafe_in_Lyndonville_Vermont.jpg

  8. 8 Photo credit: Artaxerxes https://commons.wikimedia.org/wiki/File:Grindstone_Cafe_in_Lyndonville_Vermont.jpg

  9. 9 six months later…

  10. 10 struct Event { } key: u32, name: InternedString, count:

    u32, Photo credit: Artaxerxes https://commons.wikimedia.org/wiki/File:Grindstone_Cafe_in_Lyndonville_Vermont.jpg
  11. 11 Photo credit: Gratisography https://www.pexels.com/photo/nature-walking-animal-strong-4075/ struct Event { } key:

    u32, name: InternedString, count: u32, struct InternedString { } value: Rc<String>, “reference-counted string” non-atomically reference-counted string
  12. 12 struct Event { } key: u32, name: InternedString, count:

    u32, Photo credit: Artaxerxes https://commons.wikimedia.org/wiki/File:Grindstone_Cafe_in_Lyndonville_Vermont.jpg error: the type `InternedString` does not implement `Send`
  13. 13 Zero-cost abstractions fn is_whitespace(text: &str) -> bool { text.chars()

    .all(|c| c.is_whitespace()) } fn load_images(paths: &[PathBuf]) -> Vec<Image> { paths.par_iter() .map(|path| Image::load(path)) .collect() }
  14. 14 Zero-cost abstractions Memory safety & data-race freedom + =

    Confident, productive systems programming
  15. 15 Rust the language Memory safety Traits Parallelism Unsafe Rust

    the community Rust in Firefox Community processes
  16. 16 Photo credit: Amelia Wells https://www.flickr.com/photos/speculummundi/6424242877/ Memory safety

  17. 17 Zero-cost abstractions Memory safety & data-race freedom + =

    Confident, productive systems programming
  18. Zero-cost abstractions void example() { vector<string> vector; … auto& elem

    = vector[0]; … } string [0] … elem vector data length capacity [0] [n] […] … ‘H’ … ‘e’ Stack and inline layout. Lightweight references Deterministic destruction Stack Heap C++
  19. void example() { vector<string> vector; … auto& elem = vector[0];

    vector.push_back(some_string); cout << elem; } vector data length capacity [0] … [0] [1] elem Aliasing: more than one pointer to same memory. Dangling pointer: pointer to freed memory. Mutating the vector freed old contents. C++ Memory safety
  20. ~ Ownership and Borrowing ~ Type Ownership Alias? Mutate? T

    Owned ✓
  21. Ownership n. The act, state, or right of possessing something.

    21
  22. fn main() { let mut book = Vec::new(); book.push(…); book.push(…);

    publish(book); publish(book); } fn publish(book: Vec<String>) { … } Ownership Take ownership of the vector 22 Error: use of moved value: `book` String book data length capacity [0] [1] data length capacity ~~~~~~~~~~~ Give ownership.
  23. 23 Moves compared with copy constructors:

  24. void main() { vector<string> book(); book.push_back(…); book.push_back(…); publish(book); publish(book); }

    void publish(book: vector<string>) { … } Owns the vector 24 string book data length capacity [0] [1] data length capacity [0] [1] C++ Invoke copy ctor
  25. fn main() { let mut book = Vec::new(); book.push(…); book.push(…);

    publish(book.clone()); publish(book); } fn publish(book: Vec<String>) { … } 25 string book data length capacity [0] [1] [0] [1]
  26. 26 Moves compared with copy constructors: Moves compared with rvalue

    references: …in Rust, `clone()` is explicit.
  27. data length capacity data length capacity void main() { vector<string>

    book(); book.push_back(…); book.push_back(…); publish(std::move(book)); publish(book); } void publish(book: vector<string>) { … } 27 C++ string book data length capacity [0] [1]
  28. 28 …in Rust, enforced at compilation time. Moves compared with

    copy constructors: Moves compared with rvalue references: …in Rust, `clone()` is explicit.
  29. Borrow v. To receive something with the promise of returning

    it. 29
  30. ~ Ownership and Borrowing ~ Type Ownership T Alias? Mutate?

    Owned ✓ &T Shared reference ✓
  31. fn main() { let mut book = Vec::new(); book.push(…); book.push(…);

    publish(&book); publish(&book); } fn publish(book: &Vec<String>) { … } Shared borrow Change type to a reference to a vector 31 String book data length capacity [0] [1] Borrow the vector, creating a reference book
  32. cannot mutate while shared 32 “Don’t break your friend’s toys”

    let mut book = Vec::new(); book.push(…); { let r = &book; book.push(…); r.push(…); } book.push(…); book mutable here ~~~~~~~~~~~ book borrowed here ~~~~~~~~~ * Actually: mutation only under controlled circumstances * now book is mutable again r goes out of scope; borrow ends
  33. 33 fn example() { let mut vector = Vec::new(); …

    let elem = &vector[0]; vector.push(some_string); … } vector borrowed here cannot mutate here Revisit initial example ~~~~~~~~~~~~~~~~~~~~~
  34. ~ Ownership and Borrowing ~ Type Ownership T &T Alias?

    Mutate? Owned Shared reference ✓ ✓ &mut T Mutable reference ✓
  35. fn main() { let mut book = Vec::new(); book.push(…); book.push(…);

    edit(&mut book); edit(&mut book); } fn edit(book: &mut Vec<String>) { book.push(…); } Mutable borrow Mutable reference to a vector 35 String book data length capacity [0] [1] book [2] Mutable borrow [3]
  36. cannot access while borrowed but &mut ref can mutate 36

    “No, it’s my turn now!” let mut book = Vec::new(); book.push(…); { let r = &mut book; book.len(); r.push(…); } book.push(…); book mutable here ~~~~~~~~~ book borrowed here borrow ended; accessible again r goes out of scope; borrow ends
  37. ‘l 37 Lifetime of a reference let mut book =

    Vec::new(); … { let r: &String = &book[0]; … } let r: &String = &book; let r: &’l String = &book;
  38. 38 fn first<‘a>(v: &’a Vec<String>) -> &’a String { return

    &v[0]; } “Returns a reference derived from `v`” fn first(v: &Vec<String>) -> &String { return &v[0]; } (more common shorthand)
  39. 39 fn example() { let mut book = Vec::new(); {

    let r = first(&book); book.push(…); } } ~~~~~~~~~~~ book borrowed for this span Tracking borrows across functions fn first<‘a>(v: &’a Vec<String>) -> &’a String { return &v[0]; }
  40. 40 Traits Photo credit: Andy Leppard https://www.flickr.com/photos/creativecomputer/261445720/

  41. 41 trait Clone { fn clone(&self) -> Self; } Implemented

    for a given type Method that borrows its receiver impl<T: Clone> Clone for Vec<T> { fn clone(&self) -> Vec<T> { let mut v = Vec::new(); for elem in self { v.push(elem.clone()); } return v; } } Implementation for vectors Create new vector Iterate (using references)… …push clone of each element. Return `v`
  42. 42 // “Safe to send between threads” trait Send {

    } // “Safe to memcpy” trait Copy { } String u32 Rc<String> u32 f32 String Rc<String> Marker traits ✅ Arc<String>
  43. 43 Parallelism Photo credit: Dave Gingrich https://www.flickr.com/photos/ndanger/2744507570/

  44. Library-based concurrency 44 Originally: Rust had message passing built into

    the language. Now: library-based, multi-paradigm. Libraries leverage ownership and traits to avoid data races.
  45. Data races Sharing Mutation No ordering Data race Sound familiar?

    45
  46. fn qsort(vec: &mut [i32]) { if vec.len() <= 1 {

    return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); rayon::join(|| qsort(less), || qsort(greater)); } [0] [1] [2] [3] […] [n] vec: &mut [i32] less: &mut [i32] greater: &mut [i32] `&mut` can safely go between threads — because it is unaliased! fn split_at_mut<‘a>(v: &’a mut [T], …) -> (&’a mut [T], &’a mut [T])
  47. ~ Concurrency paradigms ~ Paradigm Fork-join Ownership? Borrowing? ✓ Message

    Passing Locking ✓ ✓ ✓ Lock-free Futures … ✓ ✓ ✓ ✓
  48. 48 Unsafe

  49. Safe abstractions unsafe { … } Ownership/borrowing/traits give tools to

    enforce safe abstraction boundaries. Trust me. fn split_at_mut(…) { } Validates input, etc. 49
  50. 50 Rust compiler (~350KLOC) has approx. 4% unsafe code, much

    of which is in the LLVM bindings.
  51. 51

  52. 52 First foray: mp4 demuxer https://is.gd/idNDQw

  53. 53 Stylo and WebRender Photo credit: Fenring https://commons.wikimedia.org/wiki/File:CSS-shade.svg (Other browsers:

    0-10 FPS)
  54. 54 Community Photo credit: David McSpadden https://www.flickr.com/photos/familyclan/15535822737/

  55. 55 From http://jvns.ca/blog/2016/09/11/rustconf-keynote/ Open and welcoming

  56. Our responsibility [after 1.0] is to ensure that you never

    dread upgrading Rust. Since the early days of Rust, there have only been two things you could count on: safety, and change. And sometimes not the first one. Rust 1.0: Stability as a deliverable
  57. RFC Nightly Beta Stable ~ The feature pipeline ~

  58. None
  59. RFC Nightly Beta Stable Unstable features are available { ~

    The feature pipeline ~
  60. ~ The feature pipeline ~ RFC Nightly Beta Stable 6

    week release cycle; only stable features {
  61. Interested in Rust? 61 intorust.com users.rust-lang.org rust-lang.github.io/book ❤ #rust-beginners on

    irc.mozilla.org Also, stickers!