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

CppNow 2017

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

CppNow 2017

Keynote from CppNow 2017

Avatar for nikomatsakis

nikomatsakis

May 16, 2017
Tweet

More Decks by nikomatsakis

Other Decks in Programming

Transcript

  1. 2

  2. 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
  3. 10 struct Event { } key: u32, name: InternedString, count:

    u32, Photo credit: Artaxerxes https://commons.wikimedia.org/wiki/File:Grindstone_Cafe_in_Lyndonville_Vermont.jpg
  4. 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
  5. 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`
  6. 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() }
  7. 14 Zero-cost abstractions Memory safety & data-race freedom + =

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

    the community Rust in Firefox Community processes
  9. 17 Zero-cost abstractions Memory safety & data-race freedom + =

    Confident, productive systems programming
  10. 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++
  11. 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
  12. 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.
  13. 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
  14. 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]
  15. 26 Moves compared with copy constructors: Moves compared with rvalue

    references: …in Rust, `clone()` is explicit.
  16. 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]
  17. 28 …in Rust, enforced at compilation time. Moves compared with

    copy constructors: Moves compared with rvalue references: …in Rust, `clone()` is explicit.
  18. 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
  19. 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
  20. 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 ~~~~~~~~~~~~~~~~~~~~~
  21. ~ Ownership and Borrowing ~ Type Ownership T &T Alias?

    Mutate? Owned Shared reference ✓ ✓ &mut T Mutable reference ✓
  22. 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]
  23. 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
  24. ‘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;
  25. 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)
  26. 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]; }
  27. 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`
  28. 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>
  29. 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.
  30. 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])
  31. ~ Concurrency paradigms ~ Paradigm Fork-join Ownership? Borrowing? ✓ Message

    Passing Locking ✓ ✓ ✓ Lock-free Futures … ✓ ✓ ✓ ✓
  32. Safe abstractions unsafe { … } Ownership/borrowing/traits give tools to

    enforce safe abstraction boundaries. Trust me. fn split_at_mut(…) { } Validates input, etc. 49
  33. 51

  34. 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
  35. ~ The feature pipeline ~ RFC Nightly Beta Stable 6

    week release cycle; only stable features {